diff --git a/DEPS b/DEPS index 4541ca6..f51f949 100644 --- a/DEPS +++ b/DEPS
@@ -83,7 +83,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '687fceb29c60f59673f9368c2e2f41c7eafc1572', + 'v8_revision': 'dfa786d6715a72236941cb27a07188e71027b7b8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -91,7 +91,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': '360098d5c29fb1028e87a0d91749ad5854af0336', + 'angle_revision': '640fa5dc3f958ecdc7711038fc431e3475ae53ed', # 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. @@ -135,7 +135,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '47ca0db0bd967cf7c6f4f5ebffb47b2bd0422a8b', + 'catapult_revision': '7a160b6bb44a4fe6a4d581ecfe116663b925f1d2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -337,7 +337,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '53a62911658d6c4f830f4d5ead14134def4dffe5', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd0de9616e5bb6e4bf96bd92f05f5730b63e75a9e', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -437,7 +437,7 @@ Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'), 'src/third_party/libaddressinput/src': - Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'a575c63de328d0c72237c55d1a05e191c245122a', + Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'd955c63ec7048d59dffd20af25eeec23da878d27', 'src/third_party/libaom/source/libaom': { 'url': Var('aomedia_git') + '/aom.git' + '@' + 'cc92258a08d98f469dff1be288acbc322632377b', @@ -648,7 +648,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a182a9ad3078aca566d8355eabf2d9f56f70ee82', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '9f79a92e2642015c3f6bfde8d3c22920d7e00d98', # commit position 21742 + Var('webrtc_git') + '/src.git' + '@' + '12c8110e8c717b7f0f87615d3b99caac2a69fa6c', # commit position 21742 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc index 2f7bbe884..f03fc0bb 100644 --- a/android_webview/browser/cookie_manager.cc +++ b/android_webview/browser/cookie_manager.cc
@@ -31,6 +31,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/cookie_store_factory.h" #include "jni/AwCookieManager_jni.h" +#include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_options.h" #include "net/cookies/cookie_store.h" @@ -164,30 +165,30 @@ CookieManager(); ~CookieManager(); - void ExecCookieTaskSync(const base::Callback<void(BoolCallback)>& task); - void ExecCookieTaskSync(const base::Callback<void(IntCallback)>& task); - void ExecCookieTaskSync(const base::Callback<void(base::Closure)>& task); - void ExecCookieTask(const base::Closure& task); + void ExecCookieTaskSync(base::OnceCallback<void(BoolCallback)> task); + void ExecCookieTaskSync(base::OnceCallback<void(IntCallback)> task); + void ExecCookieTaskSync(base::OnceCallback<void(base::OnceClosure)> task); + void ExecCookieTask(base::OnceClosure task); void SetCookieHelper(const GURL& host, const std::string& value, BoolCallback callback); - void GetCookieValueAsyncHelper(const GURL& host, - std::string* result, - base::Closure complete); - void GetCookieValueCompleted(base::Closure complete, - std::string* result, - const std::string& value); + void GetCookieListAsyncHelper(const GURL& host, + net::CookieList* result, + base::OnceClosure complete); + void GetCookieListCompleted(base::OnceClosure complete, + net::CookieList* result, + const net::CookieList& value); void RemoveSessionCookiesHelper(BoolCallback callback); void RemoveAllCookiesHelper(BoolCallback callback); void RemoveCookiesCompleted(BoolCallback callback, uint32_t num_deleted); - void FlushCookieStoreAsyncHelper(base::Closure complete); + void FlushCookieStoreAsyncHelper(base::OnceClosure complete); - void HasCookiesAsyncHelper(bool* result, base::Closure complete); - void HasCookiesCompleted(base::Closure complete, + void HasCookiesAsyncHelper(bool* result, base::OnceClosure complete); + void HasCookiesCompleted(base::OnceClosure complete, bool* result, const net::CookieList& cookies); @@ -242,22 +243,22 @@ // // Ignore a bool callback. void CookieManager::ExecCookieTaskSync( - const base::Callback<void(BoolCallback)>& task) { + base::OnceCallback<void(BoolCallback)> task) { WaitableEvent completion(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - ExecCookieTask( - base::Bind(task, BoolCallbackAdapter(SignalEventClosure(&completion)))); + ExecCookieTask(base::BindOnce( + std::move(task), BoolCallbackAdapter(SignalEventClosure(&completion)))); base::ThreadRestrictions::ScopedAllowWait wait; completion.Wait(); } // Ignore an int callback. void CookieManager::ExecCookieTaskSync( - const base::Callback<void(IntCallback)>& task) { + base::OnceCallback<void(IntCallback)> task) { WaitableEvent completion(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - ExecCookieTask( - base::Bind(task, IntCallbackAdapter(SignalEventClosure(&completion)))); + ExecCookieTask(base::BindOnce( + std::move(task), IntCallbackAdapter(SignalEventClosure(&completion)))); base::ThreadRestrictions::ScopedAllowWait wait; completion.Wait(); } @@ -265,17 +266,18 @@ // Call the supplied closure when you want to signal that the blocked code can // continue. void CookieManager::ExecCookieTaskSync( - const base::Callback<void(base::Closure)>& task) { + base::OnceCallback<void(base::OnceClosure)> task) { WaitableEvent completion(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - ExecCookieTask(base::Bind(task, SignalEventClosure(&completion))); + ExecCookieTask( + base::BindOnce(std::move(task), SignalEventClosure(&completion))); base::ThreadRestrictions::ScopedAllowWait wait; completion.Wait(); } // Executes the |task| using |cookie_store_task_runner_|. -void CookieManager::ExecCookieTask(const base::Closure& task) { - cookie_store_task_runner_->PostTask(FROM_HERE, task); +void CookieManager::ExecCookieTask(base::OnceClosure task) { + cookie_store_task_runner_->PostTask(FROM_HERE, std::move(task)); } base::SingleThreadTaskRunner* CookieManager::GetCookieStoreTaskRunner() { @@ -375,29 +377,30 @@ } std::string CookieManager::GetCookie(const GURL& host) { - std::string cookie_value; - ExecCookieTaskSync(base::Bind(&CookieManager::GetCookieValueAsyncHelper, - base::Unretained(this), host, &cookie_value)); - return cookie_value; + net::CookieList cookie_list; + ExecCookieTaskSync(base::BindOnce(&CookieManager::GetCookieListAsyncHelper, + base::Unretained(this), host, + &cookie_list)); + return net::CanonicalCookie::BuildCookieLine(cookie_list); } -void CookieManager::GetCookieValueAsyncHelper(const GURL& host, - std::string* result, - base::Closure complete) { +void CookieManager::GetCookieListAsyncHelper(const GURL& host, + net::CookieList* result, + base::OnceClosure complete) { net::CookieOptions options; options.set_include_httponly(); - GetCookieStore()->GetCookiesWithOptionsAsync( + GetCookieStore()->GetCookieListWithOptionsAsync( host, options, - base::Bind(&CookieManager::GetCookieValueCompleted, - base::Unretained(this), complete, result)); + base::BindOnce(&CookieManager::GetCookieListCompleted, + base::Unretained(this), std::move(complete), result)); } -void CookieManager::GetCookieValueCompleted(base::Closure complete, - std::string* result, - const std::string& value) { +void CookieManager::GetCookieListCompleted(base::OnceClosure complete, + net::CookieList* result, + const net::CookieList& value) { *result = value; - complete.Run(); + std::move(complete).Run(); } void CookieManager::RemoveSessionCookies( @@ -428,13 +431,13 @@ std::unique_ptr<BoolCookieCallbackHolder> callback_holder) { BoolCallback callback = BoolCookieCallbackHolder::ConvertToCallback(std::move(callback_holder)); - ExecCookieTask(base::Bind(&CookieManager::RemoveAllCookiesHelper, - base::Unretained(this), callback)); + ExecCookieTask(base::BindOnce(&CookieManager::RemoveAllCookiesHelper, + base::Unretained(this), callback)); } void CookieManager::RemoveAllCookiesSync() { - ExecCookieTaskSync(base::Bind(&CookieManager::RemoveAllCookiesHelper, - base::Unretained(this))); + ExecCookieTaskSync(base::BindOnce(&CookieManager::RemoveAllCookiesHelper, + base::Unretained(this))); } void CookieManager::RemoveAllCookiesHelper(const BoolCallback callback) { @@ -449,35 +452,35 @@ } void CookieManager::FlushCookieStore() { - ExecCookieTaskSync(base::Bind(&CookieManager::FlushCookieStoreAsyncHelper, - base::Unretained(this))); + ExecCookieTaskSync(base::BindOnce(&CookieManager::FlushCookieStoreAsyncHelper, + base::Unretained(this))); } -void CookieManager::FlushCookieStoreAsyncHelper(base::Closure complete) { - GetCookieStore()->FlushStore(complete); +void CookieManager::FlushCookieStoreAsyncHelper(base::OnceClosure complete) { + GetCookieStore()->FlushStore(std::move(complete)); } bool CookieManager::HasCookies() { bool has_cookies; - ExecCookieTaskSync(base::Bind(&CookieManager::HasCookiesAsyncHelper, - base::Unretained(this), &has_cookies)); + ExecCookieTaskSync(base::BindOnce(&CookieManager::HasCookiesAsyncHelper, + base::Unretained(this), &has_cookies)); return has_cookies; } // TODO(kristianm): Simplify this, copying the entire list around // should not be needed. void CookieManager::HasCookiesAsyncHelper(bool* result, - base::Closure complete) { + base::OnceClosure complete) { GetCookieStore()->GetAllCookiesAsync( - base::Bind(&CookieManager::HasCookiesCompleted, base::Unretained(this), - complete, result)); + base::BindOnce(&CookieManager::HasCookiesCompleted, + base::Unretained(this), std::move(complete), result)); } -void CookieManager::HasCookiesCompleted(base::Closure complete, +void CookieManager::HasCookiesCompleted(base::OnceClosure complete, bool* result, const CookieList& cookies) { *result = cookies.size() != 0; - complete.Run(); + std::move(complete).Run(); } bool CookieManager::AllowFileSchemeCookies() {
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.cc b/android_webview/browser/net/aw_cookie_store_wrapper.cc index eca0bc4..3e6b3f2 100644 --- a/android_webview/browser/net/aw_cookie_store_wrapper.cc +++ b/android_webview/browser/net/aw_cookie_store_wrapper.cc
@@ -134,14 +134,6 @@ std::move(cookie), secure_source, modify_http_only, std::move(callback)); } -void GetCookiesWithOptionsAsyncOnCookieThread( - const GURL& url, - const net::CookieOptions& options, - net::CookieStore::GetCookiesCallback callback) { - GetCookieStore()->GetCookiesWithOptionsAsync(url, options, - std::move(callback)); -} - void GetCookieListWithOptionsAsyncOnCookieThread( const GURL& url, const net::CookieOptions& options, @@ -227,16 +219,6 @@ modify_http_only, CreateWrappedCallback<bool>(std::move(callback)))); } -void AwCookieStoreWrapper::GetCookiesWithOptionsAsync( - const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) { - DCHECK(client_task_runner_->RunsTasksInCurrentSequence()); - PostTaskToCookieStoreTaskRunner(base::BindOnce( - &GetCookiesWithOptionsAsyncOnCookieThread, url, options, - CreateWrappedCallback<const std::string&>(std::move(callback)))); -} - void AwCookieStoreWrapper::GetCookieListWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.h b/android_webview/browser/net/aw_cookie_store_wrapper.h index f33c12c..5e3d1a7 100644 --- a/android_webview/browser/net/aw_cookie_store_wrapper.h +++ b/android_webview/browser/net/aw_cookie_store_wrapper.h
@@ -49,9 +49,6 @@ bool secure_source, bool modify_http_only, SetCookiesCallback callback) override; - void GetCookiesWithOptionsAsync(const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) override; void GetCookieListWithOptionsAsync(const GURL& url, const net::CookieOptions& options, GetCookieListCallback callback) override;
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc index c8ffcdd..257d9f1 100644 --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc
@@ -170,11 +170,13 @@ CommandLineHelper::AddDisabledFeature(*cl, media::kMediaDrmPersistentLicense.name); - CommandLineHelper::AddDisabledFeature(*cl, features::kMojoInputMessages.name); - CommandLineHelper::AddEnabledFeature( *cl, autofill::features::kAutofillSkipComparingInferredLabels.name); + CommandLineHelper::AddDisabledFeature( + *cl, autofill::features::kAutofillRestrictUnownedFieldsToFormlessCheckout + .name); + android_webview::RegisterPathProvider(); safe_browsing_api_handler_.reset(
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 4f126d2..07c4fcb 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -723,6 +723,18 @@ "system/tray_drag_controller.h", "system/tray_tracing.cc", "system/tray_tracing.h", + "system/unified/top_shortcut_button.cc", + "system/unified/top_shortcut_button.h", + "system/unified/top_shortcuts_view.cc", + "system/unified/top_shortcuts_view.h", + "system/unified/unified_system_tray.cc", + "system/unified/unified_system_tray.h", + "system/unified/unified_system_tray_bubble.cc", + "system/unified/unified_system_tray_bubble.h", + "system/unified/unified_system_tray_controller.cc", + "system/unified/unified_system_tray_controller.h", + "system/unified/unified_system_tray_view.cc", + "system/unified/unified_system_tray_view.h", "system/update/tray_update.cc", "system/update/tray_update.h", "system/user/button_from_view.cc",
diff --git a/ash/accessibility/touch_accessibility_enabler_unittest.cc b/ash/accessibility/touch_accessibility_enabler_unittest.cc index f6d2845..6a423e1 100644 --- a/ash/accessibility/touch_accessibility_enabler_unittest.cc +++ b/ash/accessibility/touch_accessibility_enabler_unittest.cc
@@ -62,12 +62,9 @@ generator_.reset(new ui::test::EventGenerator(root_window())); - simulated_clock_ = new base::SimpleTestTickClock(); // Tests fail if time is ever 0. - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); - // ui takes ownership of the tick clock. - ui::SetEventTickClockForTesting( - std::unique_ptr<base::TickClock>(simulated_clock_)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); + ui::SetEventTickClockForTesting(&simulated_clock_); enabler_.reset(new TouchAccessibilityEnabler(root_window(), &delegate_)); } @@ -82,12 +79,11 @@ base::TimeTicks Now() { // This is the same as what EventTimeForNow() does, but here we do it // with our simulated clock. - return simulated_clock_->NowTicks(); + return simulated_clock_.NowTicks(); } std::unique_ptr<ui::test::EventGenerator> generator_; - // Owned by |ui|. - base::SimpleTestTickClock* simulated_clock_ = nullptr; + base::SimpleTestTickClock simulated_clock_; MockTouchAccessibilityEnablerDelegate delegate_; std::unique_ptr<TouchAccessibilityEnabler> enabler_; ui::GestureDetector::Config gesture_detector_config_; @@ -111,7 +107,7 @@ generator_->set_current_location(gfx::Point(11, 12)); generator_->PressTouchId(1); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(500)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(500)); generator_->set_current_location(gfx::Point(22, 34)); generator_->PressTouchId(2); @@ -160,7 +156,7 @@ enabler_->TriggerOnTimerForTesting(); EXPECT_EQ(0U, delegate_.feedback_progress_sound_count()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(3000)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(3000)); enabler_->TriggerOnTimerForTesting(); EXPECT_EQ(1U, delegate_.feedback_progress_sound_count()); } @@ -181,7 +177,7 @@ enabler_->TriggerOnTimerForTesting(); EXPECT_FALSE(delegate_.toggle_spoken_feedback()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(5000)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(5000)); enabler_->TriggerOnTimerForTesting(); EXPECT_TRUE(delegate_.toggle_spoken_feedback()); EXPECT_TRUE(delegate_.started());
diff --git a/ash/accessibility/touch_exploration_controller_unittest.cc b/ash/accessibility/touch_exploration_controller_unittest.cc index 2b170c80..c8960e92 100644 --- a/ash/accessibility/touch_exploration_controller_unittest.cc +++ b/ash/accessibility/touch_exploration_controller_unittest.cc
@@ -206,7 +206,7 @@ class TouchExplorationTest : public aura::test::AuraTestBase { public: - TouchExplorationTest() : simulated_clock_(nullptr) {} + TouchExplorationTest() {} ~TouchExplorationTest() override {} void SetUp() override { @@ -217,12 +217,10 @@ root_window()->AddPreTargetHandler(&event_capturer_); generator_.reset(new ui::test::EventGenerator(root_window())); - simulated_clock_ = new base::SimpleTestTickClock(); // Tests fail if time is ever 0. - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // ui takes ownership of the tick clock. - ui::SetEventTickClockForTesting( - std::unique_ptr<base::TickClock>(simulated_clock_)); + ui::SetEventTickClockForTesting(&simulated_clock_); cursor_client()->ShowCursor(); cursor_client()->DisableMouseEvents(); @@ -279,18 +277,18 @@ void ClearCapturedEvents() { event_capturer_.Reset(); } void AdvanceSimulatedTimePastTapDelay() { - simulated_clock_->Advance(gesture_detector_config_.double_tap_timeout); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1)); + simulated_clock_.Advance(gesture_detector_config_.double_tap_timeout); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); touch_exploration_controller_->CallTapTimerNowForTesting(); } void AdvanceSimulatedTimePastPassthroughDelay() { - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(1000)); touch_exploration_controller_->CallPassthroughTimerNowForTesting(); } void AdvanceSimulatedTimePastPotentialTapDelay() { - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(1000)); touch_exploration_controller_->CallTapTimerNowIfRunningForTesting(); } @@ -421,8 +419,7 @@ std::unique_ptr<ui::test::EventGenerator> generator_; ui::GestureDetector::Config gesture_detector_config_; - // Owned by |ui|. - base::SimpleTestTickClock* simulated_clock_; + base::SimpleTestTickClock simulated_clock_; MockTouchExplorationControllerDelegate delegate_; private: @@ -647,7 +644,7 @@ // Send a press, then add another finger after the double-tap timeout. generator_->PressTouchId(1); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(1000)); generator_->PressTouchId(2); std::vector<ui::LocatedEvent*> events = GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED); @@ -677,7 +674,7 @@ // timer fires. gfx::Point location1(33, 34); generator_->set_current_location(location1); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(301)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(301)); generator_->PressTouch(); generator_->ReleaseTouch(); AdvanceSimulatedTimePastTapDelay(); @@ -763,10 +760,10 @@ generator_->set_current_location(double_tap_location); generator_->PressTouch(); generator_->ReleaseTouch(); - simulated_clock_->Advance(gesture_detector_config_.double_tap_timeout - - base::TimeDelta::FromMilliseconds(25)); + simulated_clock_.Advance(gesture_detector_config_.double_tap_timeout - + base::TimeDelta::FromMilliseconds(25)); generator_->PressTouch(); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(50)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(50)); generator_->ReleaseTouch(); std::vector<ui::LocatedEvent*> captured_events = GetCapturedLocatedEvents(); @@ -937,7 +934,7 @@ generator_->PressTouch(); // Advance to the finger passing through, and then to the longpress timeout. AdvanceSimulatedTimePastTapDelay(); - simulated_clock_->Advance(gesture_detector_config_.longpress_timeout); + simulated_clock_.Advance(gesture_detector_config_.longpress_timeout); generator_->ReleaseTouch(); std::vector<ui::LocatedEvent*> captured_events = GetCapturedLocatedEvents(); @@ -976,7 +973,7 @@ // tapping again. gfx::Point final_location(33, 34); generator_->set_current_location(final_location); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(250)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(250)); generator_->PressTouch(); generator_->ReleaseTouch(); @@ -1152,7 +1149,7 @@ ui::ET_TOUCH_PRESSED, second_touch_location, Now(), ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)); generator_->Dispatch(&split_tap_press); - simulated_clock_->Advance(gesture_detector_config_.longpress_timeout); + simulated_clock_.Advance(gesture_detector_config_.longpress_timeout); // Placing a third finger on the screen should cancel the split tap and // enter the wait state. @@ -1267,13 +1264,13 @@ gfx::Point touch_exploration_location(20, 21); generator_->Dispatch(&first_press); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // Since we are not out of the touch slop yet, we should not be in gesture in // progress. generator_->MoveTouch(second_location); EXPECT_FALSE(IsInTouchToMouseMode()); EXPECT_FALSE(IsInGestureInProgressState()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // Once we are out of slop, we should be in GestureInProgress. generator_->MoveTouch(third_location); @@ -1495,7 +1492,7 @@ ui::ET_TOUCH_PRESSED, gfx::Point(100, 200), Now(), ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); generator_->Dispatch(&first_press); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); gfx::Point second_location(100 + distance, 200); generator_->MoveTouch(second_location); EXPECT_TRUE(IsInGestureInProgressState()); @@ -1530,14 +1527,14 @@ gfx::Point fourth_location(window_right, 35); generator_->Dispatch(&first_press); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // Since we haven't moved past slop yet, we should not be in slide gesture. generator_->MoveTouch(second_location); EXPECT_FALSE(IsInTouchToMouseMode()); EXPECT_FALSE(IsInGestureInProgressState()); EXPECT_FALSE(IsInSlideGestureState()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // Once we are out of slop, we should be in slide gesture since we are along // the edge of the screen. @@ -1590,13 +1587,13 @@ gfx::Point into_boundaries(window.right() - GetMaxDistanceFromEdge() / 2, 1); generator_->Dispatch(&first_press); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); generator_->MoveTouch(out_of_slop); EXPECT_FALSE(IsInTouchToMouseMode()); EXPECT_TRUE(IsInGestureInProgressState()); EXPECT_FALSE(IsInSlideGestureState()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // Since we did not start moving while in the boundaries, we should not be in // slide gestures. @@ -1627,7 +1624,7 @@ ui::ET_TOUCH_PRESSED, initial_press, Now(), ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); generator_->Dispatch(&first_press); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); EXPECT_FALSE(IsInGestureInProgressState()); EXPECT_FALSE(IsInSlideGestureState()); EXPECT_FALSE(IsInTouchToMouseMode()); @@ -1641,7 +1638,7 @@ EXPECT_FALSE(IsInGestureInProgressState()); EXPECT_TRUE(IsInSlideGestureState()); EXPECT_FALSE(IsInTouchToMouseMode()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); // Move the touch into slop boundaries. It should still be in slide gestures // and adjust the volume. @@ -1653,7 +1650,7 @@ EXPECT_FALSE(IsInTouchToMouseMode()); // The sound is rate limiting so it only activates every 150ms. - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(200)); size_t num_adjust_sounds = delegate_.NumAdjustSounds(); ASSERT_EQ(1U, num_adjust_sounds); @@ -1666,7 +1663,7 @@ EXPECT_TRUE(IsInSlideGestureState()); EXPECT_FALSE(IsInTouchToMouseMode()); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(200)); num_adjust_sounds = delegate_.NumAdjustSounds(); ASSERT_EQ(1U, num_adjust_sounds); ASSERT_EQ(1U, delegate_.VolumeChanges().size()); @@ -1681,7 +1678,7 @@ generator_->MoveTouch( gfx::Point(into_slop_boundaries.x() + gesture_detector_config_.touch_slop, into_slop_boundaries.y())); - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(200)); num_adjust_sounds = delegate_.NumAdjustSounds(); ASSERT_EQ(2U, num_adjust_sounds);
diff --git a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc index 6505a13d..58fdf57 100644 --- a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc +++ b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -140,6 +140,8 @@ switch (key_code) { case ui::VKEY_BROWSER_BACK: return &kKsvBrowserBackIcon; + case ui::VKEY_BROWSER_FORWARD: + return &kKsvBrowserForwardIcon; case ui::VKEY_BROWSER_REFRESH: return &kKsvReloadIcon; case ui::VKEY_MEDIA_LAUNCH_APP2:
diff --git a/ash/components/shortcut_viewer/vector_icons/BUILD.gn b/ash/components/shortcut_viewer/vector_icons/BUILD.gn index f9fb828a..124196b 100644 --- a/ash/components/shortcut_viewer/vector_icons/BUILD.gn +++ b/ash/components/shortcut_viewer/vector_icons/BUILD.gn
@@ -34,6 +34,8 @@ "ksv_brightness_up.icon", "ksv_browser_back.1x.icon", "ksv_browser_back.icon", + "ksv_browser_forward.1x.icon", + "ksv_browser_forward.icon", "ksv_fullscreen.1x.icon", "ksv_fullscreen.icon", "ksv_mute.1x.icon",
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.1x.icon new file mode 100644 index 0000000..4e5bded --- /dev/null +++ b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.1x.icon
@@ -0,0 +1,16 @@ +// 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, 16, +MOVE_TO, 8.24f, 3.5f, +LINE_TO, 13, 8.22f, +LINE_TO, 8.25f, 13, +R_LINE_TO, -1.15f, -1.13f, +R_LINE_TO, 2.8f, -2.82f, +H_LINE_TO, 3, +V_LINE_TO, 7.45f, +R_H_LINE_TO, 6.93f, +LINE_TO, 7.1f, 4.64f, +CLOSE, +END
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon new file mode 100644 index 0000000..a893357 --- /dev/null +++ b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon
@@ -0,0 +1,16 @@ +// 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, 32, +MOVE_TO, 16.49f, 7, +LINE_TO, 26, 16.43f, +LINE_TO, 16.5f, 26, +R_LINE_TO, -2.31f, -2.25f, +R_LINE_TO, 5.6f, -5.64f, +H_LINE_TO, 6, +R_V_LINE_TO, -3.21f, +R_H_LINE_TO, 13.87f, +LINE_TO, 14.2f, 9.27f, +CLOSE, +END
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon index a821470..1cb0f87 100644 --- a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon +++ b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -CANVAS_DIMENSIONS, 27, -MOVE_TO, 18, 14, -R_H_LINE_TO, -3, +CANVAS_DIMENSIONS, 16, +MOVE_TO, 12, 9, +H_LINE_TO, 9, R_V_LINE_TO, 3, -R_H_LINE_TO, -2, -R_V_LINE_TO, -3, -R_H_LINE_TO, -3, -R_V_LINE_TO, -2, -R_H_LINE_TO, 3, +H_LINE_TO, 7, V_LINE_TO, 9, +H_LINE_TO, 4, +V_LINE_TO, 7, +R_H_LINE_TO, 3, +V_LINE_TO, 4, R_H_LINE_TO, 2, R_V_LINE_TO, 3, R_H_LINE_TO, 3,
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon index 1a41ce6..65b0911 100644 --- a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon +++ b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -CANVAS_DIMENSIONS, 54, -MOVE_TO, 35, 29, +CANVAS_DIMENSIONS, 32, +MOVE_TO, 24, 18, R_H_LINE_TO, -6, R_V_LINE_TO, 6, R_H_LINE_TO, -4, R_V_LINE_TO, -6, -R_H_LINE_TO, -6, +H_LINE_TO, 8, R_V_LINE_TO, -4, R_H_LINE_TO, 6, -R_V_LINE_TO, -6, +V_LINE_TO, 8, R_H_LINE_TO, 4, R_V_LINE_TO, 6, R_H_LINE_TO, 6,
diff --git a/ash/components/shortcut_viewer/views/bubble_view.cc b/ash/components/shortcut_viewer/views/bubble_view.cc index a9322c6..0731bc3 100644 --- a/ash/components/shortcut_viewer/views/bubble_view.cc +++ b/ash/components/shortcut_viewer/views/bubble_view.cc
@@ -34,11 +34,15 @@ constexpr SkColor kShadowColor = SkColorSetARGBMacro(0x15, 0, 0, 0); shadows_ = {gfx::ShadowValue(gfx::Vector2d(kShadowXOffset, kShadowYOffset), kShadowBlur, kShadowColor)}; - // Preferred padding. - constexpr int kVerticalPadding = 6; - constexpr int kHorizontalPadding = 12; + // Preferred padding. The difference between the top and bottom paddings is to + // take acount the shadow y-offset to position the text and icon in the center + // of the bubble view. + constexpr int kVerticalTopPadding = 4; + constexpr int kVerticalBottomPadding = 6; + constexpr int kHorizontalPadding = 8; SetBorder(views::CreateEmptyBorder( - gfx::Insets(kVerticalPadding, kHorizontalPadding))); + gfx::Insets(kVerticalTopPadding, kHorizontalPadding, + kVerticalBottomPadding, kHorizontalPadding))); views::BoxLayout* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, gfx::Insets(), kIconTextSpacing)); @@ -56,7 +60,7 @@ AddChildViewAt(icon_, 0); } - constexpr int kIconSize = 18; + constexpr int kIconSize = 12; constexpr SkColor kIconColor = SkColorSetARGBMacro(0xFF, 0x5C, 0x5D, 0x60); icon_->SetImage(gfx::CreateVectorIcon(icon, kIconColor)); icon_->SetImageSize(gfx::Size(kIconSize, kIconSize)); @@ -71,7 +75,7 @@ constexpr int kLabelFontSizeDelta = 1; text_->SetFontList( ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( - kLabelFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); + kLabelFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); AddChildView(text_); } text_->SetText(text); @@ -90,7 +94,7 @@ preferred_size.Enlarge(GetInsets().width(), GetInsets().height()); // To avoid text and icon bubbles have different heights in a row. - constexpr int kMinimumHeight = 36; + constexpr int kMinimumHeight = 24; preferred_size.SetToMax(gfx::Size(kMinimumHeight, kMinimumHeight)); // Make the width to be at lease as large as the height. preferred_size.set_width(
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_list_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_list_view.cc index 90ce58d..b669b06 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_list_view.cc +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_list_view.cc
@@ -49,12 +49,15 @@ } // namespace KeyboardShortcutItemListView::KeyboardShortcutItemListView() { - constexpr int kHorizontalPadding = 32; + // The padding values are by design. Lesser padding between list view and the + // side tab than the padding between list view and the border of the window. + constexpr int kLeftPadding = 16; + constexpr int kRightPadding = 32; auto layout = std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical); layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); SetLayoutManager(std::move(layout)); - SetBorder(views::CreateEmptyBorder( - gfx::Insets(0, kHorizontalPadding, 0, kHorizontalPadding))); + SetBorder( + views::CreateEmptyBorder(gfx::Insets(0, kLeftPadding, 0, kRightPadding))); } void KeyboardShortcutItemListView::AddCategoryLabel( @@ -68,9 +71,10 @@ category_label->SetBorder(views::CreateEmptyBorder( gfx::Insets(kLabelTopPadding, 0, kLabelBottomPadding, 0))); category_label->SetEnabledColor(kLabelColor); + constexpr int kLabelFontSizeDelta = 1; category_label->SetFontList( ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( - ui::kLabelFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); + kLabelFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); AddChildView(category_label); }
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc index be3590f9..4a6ae11 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc
@@ -27,7 +27,7 @@ std::unique_ptr<views::View> CreateSeparatorView() { constexpr SkColor kSeparatorColor = SkColorSetARGBMacro(0xFF, 0x1A, 0x73, 0xE8); - constexpr int kIconSize = 27; + constexpr int kIconSize = 16; std::unique_ptr<views::ImageView> separator_view = std::make_unique<views::ImageView>(); @@ -130,20 +130,27 @@ if (width <= 0) return; - constexpr int kDescriptionViewPreferredWidth = 210; - constexpr int kShortcutViewPreferredWidth = 268; + // The width of |description_label_view_| and |shortcut_label_view_| as a + // ratio of its parent view's width. The unused width is to have some spacing + // in between the two views. + constexpr float kDescriptionViewPreferredWidthRatio = 0.32f; + constexpr float kShortcutViewPreferredWidthRatio = 0.65f; + const int description_view_preferred_width = + width * kDescriptionViewPreferredWidthRatio; + const int shortcut_view_preferred_width = + width * kShortcutViewPreferredWidthRatio; const int description_view_height = description_label_view_->GetHeightForWidth( - kDescriptionViewPreferredWidth); + description_view_preferred_width); const int shortcut_view_height = - shortcut_label_view_->GetHeightForWidth(kShortcutViewPreferredWidth); + shortcut_label_view_->GetHeightForWidth(shortcut_view_preferred_width); // Sets the bounds and layout in order to get the center points of the views // making up the top lines in both the description and shortcut views. // We want the center of the top lines in both views to align with each other. - description_label_view_->SetBounds(0, 0, kDescriptionViewPreferredWidth, + description_label_view_->SetBounds(0, 0, description_view_preferred_width, description_view_height); - shortcut_label_view_->SetBounds(0, 0, kShortcutViewPreferredWidth, + shortcut_label_view_->SetBounds(0, 0, shortcut_view_preferred_width, shortcut_view_height); DCHECK(shortcut_label_view_->has_children() && @@ -165,12 +172,12 @@ const int top = insets.top(); // Left align the |description_label_view_|. description_label_view_->SetBoundsRect( - gfx::Rect(left, top + description_delta_y, kDescriptionViewPreferredWidth, - description_view_height)); + gfx::Rect(left, top + description_delta_y, + description_view_preferred_width, description_view_height)); // Right align the |shortcut_label_view_|. shortcut_label_view_->SetBoundsRect( - gfx::Rect(left + width - kShortcutViewPreferredWidth, top, - kShortcutViewPreferredWidth, shortcut_view_height)); + gfx::Rect(left + width - shortcut_view_preferred_width, top, + shortcut_view_preferred_width, shortcut_view_height)); // Add 2 * |description_delta_y| to balance the top and bottom paddings. const int total_height = std::max(shortcut_view_height,
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc index 3b798e62..f652a9e6 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -51,9 +51,11 @@ SkColorSetARGBMacro(0xFF, 0xDA, 0xDC, 0xE0); illustration_view->set_owned_by_client(); - views::BoxLayout* layout = illustration_view->SetLayoutManager( - std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); - layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); + constexpr int kTopPadding = 98; + views::BoxLayout* layout = + illustration_view->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, gfx::Insets(kTopPadding, 0, 0, 0))); + layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); views::ImageView* image_view = new views::ImageView(); image_view->SetImage( gfx::CreateVectorIcon(icon, kSearchIllustrationIconColor)); @@ -68,7 +70,7 @@ constexpr int kLabelFontSizeDelta = 1; ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); text->SetFontList(rb.GetFontListWithDelta( - kLabelFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); + kLabelFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); illustration_view->AddChildView(text); } @@ -94,14 +96,13 @@ g_ksv_view->GetWidget()->Activate(); } else { constexpr gfx::Size kKSVWindowSize(768, 512); - gfx::Point offset; + gfx::Rect window_bounds(kKSVWindowSize); if (context) { - gfx::Rect root_bounds(context->GetRootWindow()->bounds()); - offset.SetPoint((root_bounds.width() - kKSVWindowSize.width()) / 2, - (root_bounds.height() - kKSVWindowSize.height()) / 2); + window_bounds = context->GetRootWindow()->bounds(); + window_bounds.ClampToCenteredSize(kKSVWindowSize); } - views::Widget::CreateWindowWithContextAndBounds( - new KeyboardShortcutView(), context, gfx::Rect(offset, kKSVWindowSize)); + views::Widget::CreateWindowWithContextAndBounds(new KeyboardShortcutView(), + context, window_bounds); // Set frame view Active and Inactive colors, both are SK_ColorWHITE. aura::Window* window = g_ksv_view->GetWidget()->GetNativeWindow(); @@ -168,9 +169,6 @@ std::make_unique<views::FillLayout>()); search_results_container_->AddChildView(search_start_view_.get()); search_results_container_->SetVisible(false); - constexpr int kHorizontalPadding = 96; - search_results_container_->SetBorder(views::CreateEmptyBorder( - gfx::Insets(0, kHorizontalPadding, 0, kHorizontalPadding))); AddChildView(search_results_container_); // Init views of KeyboardShortcutItemView. @@ -182,7 +180,10 @@ } std::sort(shortcut_views_.begin(), shortcut_views_.end(), [](KeyboardShortcutItemView* lhs, KeyboardShortcutItemView* rhs) { - return lhs->category() < rhs->category(); + if (lhs->category() != rhs->category()) + return lhs->category() < rhs->category(); + return lhs->description_label_view()->text() < + rhs->description_label_view()->text(); }); // Init views of TabbedPane and KeyboardShortcutItemListView. @@ -240,9 +241,13 @@ constexpr int kSearchBoxTopPadding = 8; constexpr int kSearchBoxBottomPadding = 16; + constexpr int kSearchBoxHorizontalPadding = 32; const int left = content_bounds.x(); const int top = content_bounds.y(); gfx::Rect search_box_bounds(search_box_view_->GetPreferredSize()); + search_box_bounds.set_width( + std::min(search_box_bounds.width(), + content_bounds.width() - 2 * kSearchBoxHorizontalPadding)); search_box_bounds.set_x( left + (content_bounds.width() - search_box_bounds.width()) / 2); search_box_bounds.set_y(top + kSearchBoxTopPadding); @@ -321,6 +326,12 @@ } if (found_items_list_view->has_children()) { + // To offset the padding between the bottom of the |search_box_view_| and + // the top of the |search_results_container_|. + constexpr int kTopPadding = -16; + constexpr int kHorizontalPadding = 128; + found_items_list_view->SetBorder(views::CreateEmptyBorder( + gfx::Insets(kTopPadding, kHorizontalPadding, 0, kHorizontalPadding))); views::ScrollView* const scroller = CreateScrollView(); scroller->SetContents(found_items_list_view.release()); search_container_content_view = scroller;
diff --git a/ash/components/shortcut_viewer/views/ksv_search_box_view.cc b/ash/components/shortcut_viewer/views/ksv_search_box_view.cc index 7af5de4b..790a6f6 100644 --- a/ash/components/shortcut_viewer/views/ksv_search_box_view.cc +++ b/ash/components/shortcut_viewer/views/ksv_search_box_view.cc
@@ -18,7 +18,7 @@ namespace { constexpr SkColor kDefaultSearchBoxBackgroundColor = - SkColorSetARGBMacro(0x1E, 0x80, 0x86, 0x8B); + SkColorSetARGBMacro(0x28, 0x80, 0x86, 0x8B); constexpr int kIconSize = 20; @@ -34,6 +34,10 @@ search_box()->SetBackgroundColor(SK_ColorTRANSPARENT); search_box()->set_placeholder_text( l10n_util::GetStringUTF16(IDS_KSV_SEARCH_BOX_PLACEHOLDER)); + constexpr SkColor kSearchBoxTextColor = + SkColorSetARGBMacro(0xFF, 0x3C, 0x40, 0x43); + search_box()->SetColor(kSearchBoxTextColor); + search_box()->set_placeholder_text_color(kSearchBoxTextColor); search_box()->set_placeholder_text_draw_flags(gfx::Canvas::TEXT_ALIGN_CENTER); search_box()->SetAccessibleName( l10n_util::GetStringUTF16(IDS_KSV_SEARCH_BOX_ACCESSIBILITY_NAME));
diff --git a/ash/magnifier/docked_magnifier_controller.cc b/ash/magnifier/docked_magnifier_controller.cc index b2bacff6..aae1202 100644 --- a/ash/magnifier/docked_magnifier_controller.cc +++ b/ash/magnifier/docked_magnifier_controller.cc
@@ -351,6 +351,19 @@ CenterOnPoint(GetCursorScreenPoint()); } +bool DockedMagnifierController::GetFullscreenMagnifierEnabled() const { + return active_user_pref_service_ && + active_user_pref_service_->GetBoolean( + prefs::kAccessibilityScreenMagnifierEnabled); +} + +void DockedMagnifierController::SetFullscreenMagnifierEnabled(bool enabled) { + if (active_user_pref_service_) { + active_user_pref_service_->SetBoolean( + prefs::kAccessibilityScreenMagnifierEnabled, enabled); + } +} + void DockedMagnifierController::FlushClientPtrForTesting() { client_.FlushForTesting(); } @@ -450,6 +463,11 @@ prefs::kDockedMagnifierScale, base::BindRepeating(&DockedMagnifierController::OnScalePrefChanged, base::Unretained(this))); + pref_change_registrar_->Add( + prefs::kAccessibilityScreenMagnifierEnabled, + base::BindRepeating( + &DockedMagnifierController::OnFullscreenMagnifierEnabledPrefChanged, + base::Unretained(this))); OnEnabledPrefChanged(); NotifyClientWithStatusChanged(); @@ -458,6 +476,8 @@ void DockedMagnifierController::OnEnabledPrefChanged() { Shell* shell = Shell::Get(); if (GetEnabled()) { + // Enabling the Docked Magnifier disables the Fullscreen Magnifier. + SetFullscreenMagnifierEnabled(false); // Calling refresh will result in the creation of the magnifier viewport and // its associated layers. Refresh(); @@ -496,6 +516,12 @@ } } +void DockedMagnifierController::OnFullscreenMagnifierEnabledPrefChanged() { + // Enabling the Fullscreen Magnifier disables the Docked Magnifier. + if (GetFullscreenMagnifierEnabled()) + SetEnabled(false); +} + void DockedMagnifierController::Refresh() { DCHECK(GetEnabled()); CenterOnPoint(GetCursorScreenPoint());
diff --git a/ash/magnifier/docked_magnifier_controller.h b/ash/magnifier/docked_magnifier_controller.h index 7d46fcb..24428afb 100644 --- a/ash/magnifier/docked_magnifier_controller.h +++ b/ash/magnifier/docked_magnifier_controller.h
@@ -98,6 +98,18 @@ // ash::WindowTreeHostManager::Observer: void OnDisplayConfigurationChanged() override; + // Getters and setters of the enabled status of the Fullscreen Magnifier. + // We need these so that we can guarantee that both magnifiers are mutually + // exclusive (i.e. only one can be on at the same time). + // Note: We can't use the ash::MagnificationController since it's not hooked + // to the associated user-prefs except when Chrome is running (via + // chromeos::MagnificationManager), so we can't assert this behavior in + // ash_unittests. Keep them public for now. + // TODO(afakhry): Refactor the Fullscreen Magnifier and remove these + // functions. https://crbug.com/817157. + bool GetFullscreenMagnifierEnabled() const; + void SetFullscreenMagnifierEnabled(bool enabled); + void FlushClientPtrForTesting(); const views::Widget* GetViewportWidgetForTesting() const; @@ -123,6 +135,7 @@ // Handlers of prefs changes. void OnEnabledPrefChanged(); void OnScalePrefChanged(); + void OnFullscreenMagnifierEnabledPrefChanged(); void Refresh();
diff --git a/ash/magnifier/docked_magnifier_controller_unittest.cc b/ash/magnifier/docked_magnifier_controller_unittest.cc index d9da8901..2660ff7 100644 --- a/ash/magnifier/docked_magnifier_controller_unittest.cc +++ b/ash/magnifier/docked_magnifier_controller_unittest.cc
@@ -116,6 +116,32 @@ DISALLOW_COPY_AND_ASSIGN(DockedMagnifierTest); }; +// Tests that the Fullscreen and Docked Magnifiers are mutually exclusive. +// TODO(afakhry): Update this test to use ash::MagnificationController once +// refactored. https://crbug.com/817157. +TEST_F(DockedMagnifierTest, MutuallyExclusiveMagnifiers) { + // Start with both magnifiers disabled. + EXPECT_FALSE(controller()->GetEnabled()); + EXPECT_FALSE(controller()->GetFullscreenMagnifierEnabled()); + + // Enabling one disables the other. + controller()->SetEnabled(true); + EXPECT_TRUE(controller()->GetEnabled()); + EXPECT_FALSE(controller()->GetFullscreenMagnifierEnabled()); + + controller()->SetFullscreenMagnifierEnabled(true); + EXPECT_FALSE(controller()->GetEnabled()); + EXPECT_TRUE(controller()->GetFullscreenMagnifierEnabled()); + + controller()->SetEnabled(true); + EXPECT_TRUE(controller()->GetEnabled()); + EXPECT_FALSE(controller()->GetFullscreenMagnifierEnabled()); + + controller()->SetEnabled(false); + EXPECT_FALSE(controller()->GetEnabled()); + EXPECT_FALSE(controller()->GetFullscreenMagnifierEnabled()); +} + // Tests the changes in the magnifier's status, user switches and the // interaction with the client. TEST_F(DockedMagnifierTest, TestEnableAndDisable) {
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc index 0f1d301..3c2e40bf 100644 --- a/ash/magnifier/magnification_controller.cc +++ b/ash/magnifier/magnification_controller.cc
@@ -138,7 +138,7 @@ // For test gfx::Point GetPointOfInterestForTesting() override { - return point_of_interest_; + return point_of_interest_in_root_; } bool IsOnAnimationForTesting() const override { return is_on_animation_; } @@ -297,7 +297,7 @@ // Stores the last mouse cursor (or last touched) location. This value is // used on zooming to keep this location visible. - gfx::Point point_of_interest_; + gfx::Point point_of_interest_in_root_; // Current scale, origin (left-top) position of the magnification window. float scale_; @@ -362,7 +362,7 @@ root_window_->AddObserver(this); root_window_->GetHost()->GetEventSource()->AddEventRewriter(this); - point_of_interest_ = root_window_->bounds().CenterPoint(); + point_of_interest_in_root_ = root_window_->bounds().CenterPoint(); gesture_provider_client_ = std::make_unique<GestureProviderClient>(); gesture_provider_ = std::make_unique<ui::GestureProviderAura>( @@ -384,7 +384,7 @@ float scale, bool animate, bool ignore_mouse_change) { - gfx::Point mouse_in_root = point_of_interest_; + gfx::Point mouse_in_root = point_of_interest_in_root_; // mouse_in_root is invalid value when the cursor is hidden. if (!root_window_->bounds().Contains(mouse_in_root)) mouse_in_root = root_window_->bounds().CenterPoint(); @@ -634,7 +634,7 @@ CHECK_NE(target_root_window, root_window); // Don't redraw the old root window as it's being destroyed. SwitchTargetRootWindow(target_root_window, false); - point_of_interest_ = target_root_window->bounds().CenterPoint(); + point_of_interest_in_root_ = target_root_window->bounds().CenterPoint(); } } @@ -736,7 +736,7 @@ if (root_bounds.Contains(event->root_location())) { // This must be before |SwitchTargetRootWindow()|. if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) - point_of_interest_ = event->root_location(); + point_of_interest_in_root_ = event->root_location(); if (current_root != root_window_) { DCHECK(current_root); @@ -783,11 +783,15 @@ void MagnificationControllerImpl::OnTouchEvent(ui::TouchEvent* event) { aura::Window* target = static_cast<aura::Window*>(event->target()); aura::Window* current_root = target->GetRootWindow(); - if (current_root == root_window_) { - gfx::Rect root_bounds = current_root->bounds(); - if (root_bounds.Contains(event->root_location())) - point_of_interest_ = event->root_location(); - } + + gfx::Rect root_bounds = current_root->bounds(); + if (!root_bounds.Contains(event->root_location())) + return; + + point_of_interest_in_root_ = event->root_location(); + + if (current_root != root_window_) + SwitchTargetRootWindow(current_root, true); } ui::EventRewriteStatus MagnificationControllerImpl::RewriteEvent(
diff --git a/ash/magnifier/magnification_controller.h b/ash/magnifier/magnification_controller.h index f24e9b1d..6c1ba4ef 100644 --- a/ash/magnifier/magnification_controller.h +++ b/ash/magnifier/magnification_controller.h
@@ -75,8 +75,8 @@ bool is_editable_node, const gfx::Rect& node_bounds_in_screen) = 0; - // Returns |point_of_interest_| in MagnificationControllerImpl. This is - // the internal variable to stores the last mouse cursor (or last touched) + // Returns |point_of_interest_in_root_| in MagnificationControllerImpl. This + // is the internal variable to stores the last mouse cursor (or last touched) // location. This method is only for test purpose. virtual gfx::Point GetPointOfInterestForTesting() = 0;
diff --git a/ash/magnifier/magnification_controller_unittest.cc b/ash/magnifier/magnification_controller_unittest.cc index db9516ad..8494333 100644 --- a/ash/magnifier/magnification_controller_unittest.cc +++ b/ash/magnifier/magnification_controller_unittest.cc
@@ -717,6 +717,28 @@ EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity()); } +TEST_F(MagnificationControllerTest, MoveToSecondDisplayWithTouch) { + UpdateDisplay("0+0-500x500, 500+0-500x500"); + EXPECT_EQ(2ul, display::Screen::GetScreen()->GetAllDisplays().size()); + + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + GetEventGenerator().GestureTapAt(gfx::Point(250, 250)); + ASSERT_TRUE(root_windows[0]->layer()->transform().IsIdentity()); + ASSERT_TRUE(root_windows[1]->layer()->transform().IsIdentity()); + + GetMagnificationController()->SetEnabled(true); + EXPECT_FALSE(root_windows[0]->layer()->transform().IsIdentity()); + EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity()); + + GetEventGenerator().GestureTapAt(gfx::Point(750, 250)); + EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity()); + EXPECT_FALSE(root_windows[1]->layer()->transform().IsIdentity()); + + GetMagnificationController()->SetEnabled(false); + EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity()); + EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity()); +} + TEST_F(MagnificationControllerTest, AdjustScaleFromScroll) { // 0 to 1 maps to 1 to 20 EXPECT_EQ(1.0f, GetMagnificationController()->GetScale());
diff --git a/ash/message_center/message_center_style.h b/ash/message_center/message_center_style.h index d82d510..483461c 100644 --- a/ash/message_center/message_center_style.h +++ b/ash/message_center/message_center_style.h
@@ -6,6 +6,7 @@ #define ASH_MESSAGE_CENTER_MESSAGE_CENTER_STYLE_H_ #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/insets.h" @@ -16,8 +17,8 @@ constexpr SkColor kBackgroundColor = SkColorSetRGB(0xFF, 0xFF, 0xFF); constexpr SkColor kEmptyViewColor = SkColorSetARGB(0x8A, 0x0, 0x0, 0x0); constexpr SkColor kScrollShadowColor = SkColorSetARGB(0x24, 0x0, 0x0, 0x0); -constexpr SkColor kActiveButtonColor = SkColorSetARGB(0xFF, 0x5A, 0x5A, 0x5A); -constexpr SkColor kInactiveButtonColor = SkColorSetARGB(0x8A, 0x5A, 0x5A, 0x5A); +constexpr SkColor kActiveButtonColor = gfx::kChromeIconGrey; +constexpr SkColor kInactiveButtonColor = SkColorSetA(kActiveButtonColor, 0xB3); constexpr int kActionIconSize = 20; constexpr int kEmptyIconSize = 24;
diff --git a/ash/metrics/task_switch_time_tracker.cc b/ash/metrics/task_switch_time_tracker.cc index 63b39cb2..2c30dd0 100644 --- a/ash/metrics/task_switch_time_tracker.cc +++ b/ash/metrics/task_switch_time_tracker.cc
@@ -26,13 +26,12 @@ } // namespace TaskSwitchTimeTracker::TaskSwitchTimeTracker(const std::string& histogram_name) - : histogram_name_(histogram_name), - tick_clock_(new base::DefaultTickClock()) {} + : TaskSwitchTimeTracker(histogram_name, + base::DefaultTickClock::GetInstance()) {} -TaskSwitchTimeTracker::TaskSwitchTimeTracker( - const std::string& histogram_name, - std::unique_ptr<base::TickClock> tick_clock) - : histogram_name_(histogram_name), tick_clock_(tick_clock.release()) {} +TaskSwitchTimeTracker::TaskSwitchTimeTracker(const std::string& histogram_name, + base::TickClock* tick_clock) + : histogram_name_(histogram_name), tick_clock_(tick_clock) {} TaskSwitchTimeTracker::~TaskSwitchTimeTracker() = default;
diff --git a/ash/metrics/task_switch_time_tracker.h b/ash/metrics/task_switch_time_tracker.h index 552bffac..5e45d1f 100644 --- a/ash/metrics/task_switch_time_tracker.h +++ b/ash/metrics/task_switch_time_tracker.h
@@ -37,8 +37,10 @@ // Private constructor that the TaskSwitchTimeTrackerTestAPI can use to // inject a custom |tick_clock|. + // This doesn't take the ownership of the clock. |tick_clock| must outlive + // TaskSwitchTimeTracker. TaskSwitchTimeTracker(const std::string& histogram_name, - std::unique_ptr<base::TickClock> tick_clock); + base::TickClock* tick_clock); // Returns true if |last_action_time_| has a valid value. bool HasLastActionTime() const; @@ -64,7 +66,7 @@ base::TimeTicks last_action_time_ = base::TimeTicks(); // The clock used to determine the |last_action_time_|. - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; DISALLOW_COPY_AND_ASSIGN(TaskSwitchTimeTracker); };
diff --git a/ash/metrics/task_switch_time_tracker_test_api.cc b/ash/metrics/task_switch_time_tracker_test_api.cc index c26ec6a..e5176ab 100644 --- a/ash/metrics/task_switch_time_tracker_test_api.cc +++ b/ash/metrics/task_switch_time_tracker_test_api.cc
@@ -5,23 +5,18 @@ #include "ash/metrics/task_switch_time_tracker_test_api.h" #include "ash/metrics/task_switch_time_tracker.h" -#include "base/test/simple_test_tick_clock.h" namespace ash { TaskSwitchTimeTrackerTestAPI::TaskSwitchTimeTrackerTestAPI( const std::string& histogram_name) { - tick_clock_ = new base::SimpleTestTickClock(); - time_tracker_.reset(new TaskSwitchTimeTracker( - histogram_name, std::unique_ptr<base::TickClock>(tick_clock_))); + time_tracker_.reset(new TaskSwitchTimeTracker(histogram_name, &tick_clock_)); } -TaskSwitchTimeTrackerTestAPI::~TaskSwitchTimeTrackerTestAPI() { - tick_clock_ = nullptr; -} +TaskSwitchTimeTrackerTestAPI::~TaskSwitchTimeTrackerTestAPI() {} void TaskSwitchTimeTrackerTestAPI::Advance(base::TimeDelta time_delta) { - tick_clock_->Advance(time_delta); + tick_clock_.Advance(time_delta); } bool TaskSwitchTimeTrackerTestAPI::HasLastActionTime() const {
diff --git a/ash/metrics/task_switch_time_tracker_test_api.h b/ash/metrics/task_switch_time_tracker_test_api.h index 7468ac6..d4de46c 100644 --- a/ash/metrics/task_switch_time_tracker_test_api.h +++ b/ash/metrics/task_switch_time_tracker_test_api.h
@@ -9,12 +9,9 @@ #include <string> #include "base/macros.h" +#include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" -namespace base { -class SimpleTestTickClock; -} // namespace base - namespace ash { class TaskSwitchTimeTracker; @@ -37,8 +34,7 @@ bool HasLastActionTime() const; private: - // Owned by |time_tracker_|. - base::SimpleTestTickClock* tick_clock_; + base::SimpleTestTickClock tick_clock_; // The TaskSwitchTimeTracker to provide internal access to. std::unique_ptr<TaskSwitchTimeTracker> time_tracker_;
diff --git a/ash/shelf/shelf_button_pressed_metric_tracker.cc b/ash/shelf/shelf_button_pressed_metric_tracker.cc index 324c5da..16a3c25 100644 --- a/ash/shelf/shelf_button_pressed_metric_tracker.cc +++ b/ash/shelf/shelf_button_pressed_metric_tracker.cc
@@ -17,7 +17,7 @@ "Ash.Shelf.TimeBetweenWindowMinimizedAndActivatedActions"; ShelfButtonPressedMetricTracker::ShelfButtonPressedMetricTracker() - : tick_clock_(new base::DefaultTickClock()), + : tick_clock_(base::DefaultTickClock::GetInstance()), time_of_last_minimize_(base::TimeTicks()), last_minimized_source_button_(nullptr) {}
diff --git a/ash/shelf/shelf_button_pressed_metric_tracker.h b/ash/shelf/shelf_button_pressed_metric_tracker.h index fad0a94..0d12886 100644 --- a/ash/shelf/shelf_button_pressed_metric_tracker.h +++ b/ash/shelf/shelf_button_pressed_metric_tracker.h
@@ -70,7 +70,7 @@ void ResetMinimizedData(); // Time source for performed action times. - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; // Stores the time of the last window minimize action. base::TimeTicks time_of_last_minimize_;
diff --git a/ash/shelf/shelf_button_pressed_metric_tracker_test_api.cc b/ash/shelf/shelf_button_pressed_metric_tracker_test_api.cc index 3278e6d..bc14b28 100644 --- a/ash/shelf/shelf_button_pressed_metric_tracker_test_api.cc +++ b/ash/shelf/shelf_button_pressed_metric_tracker_test_api.cc
@@ -17,8 +17,8 @@ ~ShelfButtonPressedMetricTrackerTestAPI() = default; void ShelfButtonPressedMetricTrackerTestAPI::SetTickClock( - std::unique_ptr<base::TickClock> tick_clock) { - shelf_button_pressed_metric_tracker_->tick_clock_ = std::move(tick_clock); + base::TickClock* tick_clock) { + shelf_button_pressed_metric_tracker_->tick_clock_ = tick_clock; } } // namespace ash
diff --git a/ash/shelf/shelf_button_pressed_metric_tracker_test_api.h b/ash/shelf/shelf_button_pressed_metric_tracker_test_api.h index 2dfe1929..10e8a8a1 100644 --- a/ash/shelf/shelf_button_pressed_metric_tracker_test_api.h +++ b/ash/shelf/shelf_button_pressed_metric_tracker_test_api.h
@@ -25,7 +25,9 @@ ~ShelfButtonPressedMetricTrackerTestAPI(); // Set's the |tick_clock_| on the internal ShelfButtonPressedMetricTracker. - void SetTickClock(std::unique_ptr<base::TickClock> tick_clock); + // This doesn't take the ownership of the clock. |tick_clock| must outlive the + // ShelfButtonPressedMetricTracker instance. + void SetTickClock(base::TickClock* tick_clock); private: ShelfButtonPressedMetricTracker* shelf_button_pressed_metric_tracker_;
diff --git a/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc b/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc index 698e8016..49c0655 100644 --- a/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc +++ b/ash/shelf/shelf_button_pressed_metric_tracker_unittest.cc
@@ -85,7 +85,7 @@ ShelfButtonPressedMetricTracker* metric_tracker_; // The TickClock injected in to the test target. - base::SimpleTestTickClock* tick_clock_; + base::SimpleTestTickClock tick_clock_; private: DISALLOW_COPY_AND_ASSIGN(ShelfButtonPressedMetricTrackerTest); @@ -112,19 +112,14 @@ ShelfButtonPressedMetricTrackerTestAPI test_api(metric_tracker_); - std::unique_ptr<base::TickClock> test_tick_clock( - new base::SimpleTestTickClock()); - tick_clock_ = static_cast<base::SimpleTestTickClock*>(test_tick_clock.get()); - test_api.SetTickClock(std::move(test_tick_clock)); + test_api.SetTickClock(&tick_clock_); // Ensure the TickClock->NowTicks() doesn't return base::TimeTicks because // ShelfButtonPressedMetricTracker interprets that value as unset. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(100)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100)); } void ShelfButtonPressedMetricTrackerTest::TearDown() { - tick_clock_ = nullptr; - AshTestBase::TearDown(); } @@ -280,7 +275,7 @@ base::HistogramTester histogram_tester; ButtonPressed(&kDummyButton, SHELF_ACTION_WINDOW_MINIMIZED); - tick_clock_->Advance( + tick_clock_.Advance( base::TimeDelta::FromMilliseconds(kTimeDeltaInMilliseconds)); ButtonPressed(&kDummyButton, SHELF_ACTION_WINDOW_ACTIVATED);
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc index 8b253e91..7a2eeae 100644 --- a/ash/system/palette/palette_tray_unittest.cc +++ b/ash/system/palette/palette_tray_unittest.cc
@@ -247,11 +247,9 @@ // the simulated clock that is being installed below. GetEventGenerator(); - simulated_clock_ = new base::SimpleTestTickClock(); // Tests fail if event time is ever 0. - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); - // ui takes ownership of the tick clock. - ui::SetEventTickClockForTesting(base::WrapUnique(simulated_clock_)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); + ui::SetEventTickClockForTesting(&simulated_clock_); highlighter_test_api_ = std::make_unique<HighlighterControllerTestApi>( Shell::Get()->highlighter_controller()); @@ -312,7 +310,7 @@ bool expected, bool expected_on_press) { const int kStrokeGap = 1000; - simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(kStrokeGap)); + simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(kStrokeGap)); DragAndAssertMetalayer(context, origin, event_flags, expected, expected_on_press); } @@ -320,8 +318,7 @@ std::unique_ptr<HighlighterControllerTestApi> highlighter_test_api_; private: - // Owned by |ui|. - base::SimpleTestTickClock* simulated_clock_ = nullptr; + base::SimpleTestTickClock simulated_clock_; DISALLOW_COPY_AND_ASSIGN(PaletteTrayTestWithVoiceInteraction); };
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc index 94475ba..2fb240e 100644 --- a/ash/system/power/power_button_controller.cc +++ b/ash/system/power/power_button_controller.cc
@@ -38,11 +38,11 @@ BacklightsForcedOffSetter* backlights_forced_off_setter) : backlights_forced_off_setter_(backlights_forced_off_setter), lock_state_controller_(Shell::Get()->lock_state_controller()), - tick_clock_(new base::DefaultTickClock), + tick_clock_(base::DefaultTickClock::GetInstance()), weak_factory_(this) { ProcessCommandLine(); display_controller_ = std::make_unique<PowerButtonDisplayController>( - backlights_forced_off_setter_, tick_clock_.get()); + backlights_forced_off_setter_, tick_clock_); chromeos::PowerManagerClient* power_manager_client = chromeos::DBusThreadManager::Get()->GetPowerManagerClient(); power_manager_client->AddObserver(this); @@ -246,12 +246,12 @@ } void PowerButtonController::SetTickClockForTesting( - std::unique_ptr<base::TickClock> tick_clock) { + base::TickClock* tick_clock) { DCHECK(tick_clock); - tick_clock_ = std::move(tick_clock); + tick_clock_ = tick_clock; display_controller_ = std::make_unique<PowerButtonDisplayController>( - backlights_forced_off_setter_, tick_clock_.get()); + backlights_forced_off_setter_, tick_clock_); } bool PowerButtonController::TriggerDisplayOffTimerForTesting() { @@ -283,13 +283,12 @@ if (!force_clamshell_power_button_ && !tablet_controller_) { tablet_controller_ = std::make_unique<TabletPowerButtonController>( display_controller_.get(), backlights_forced_off_setter_, - show_power_button_menu_, tick_clock_.get()); + show_power_button_menu_, tick_clock_); } if (!screenshot_controller_) { screenshot_controller_ = std::make_unique<PowerButtonScreenshotController>( - tablet_controller_.get(), tick_clock_.get(), - force_clamshell_power_button_); + tablet_controller_.get(), tick_clock_, force_clamshell_power_button_); } }
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h index dfdae678..330b873 100644 --- a/ash/system/power/power_button_controller.h +++ b/ash/system/power/power_button_controller.h
@@ -86,7 +86,7 @@ scoped_refptr<const chromeos::AccelerometerUpdate> update) override; // Overrides the tick clock used by |this| for testing. - void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock); + void SetTickClockForTesting(base::TickClock* tick_clock); // If |display_off_timer_| is running, stops it, runs its task, and returns // true. Otherwise, returns false. @@ -156,7 +156,7 @@ LockStateController* lock_state_controller_; // Not owned. // Time source for performed action times. - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; // Used to interact with the display. std::unique_ptr<PowerButtonDisplayController> display_controller_;
diff --git a/ash/system/power/power_button_screenshot_controller_unittest.cc b/ash/system/power/power_button_screenshot_controller_unittest.cc index 9684587..bbd2e99 100644 --- a/ash/system/power/power_button_screenshot_controller_unittest.cc +++ b/ash/system/power/power_button_screenshot_controller_unittest.cc
@@ -38,7 +38,7 @@ // Advance a duration longer than |kIgnorePowerButtonAfterResumeDelay| to // avoid events being ignored. - tick_clock_->Advance( + tick_clock_.Advance( TabletPowerButtonController::kIgnorePowerButtonAfterResumeDelay + base::TimeDelta::FromMilliseconds(2)); } @@ -127,22 +127,22 @@ TEST_F(PowerButtonScreenshotControllerTest, PowerButtonPressedFirst_ScreenshotChord) { PressPowerButton(); - tick_clock_->Advance(PowerButtonScreenshotController::kScreenshotChordDelay - - base::TimeDelta::FromMilliseconds(2)); + tick_clock_.Advance(PowerButtonScreenshotController::kScreenshotChordDelay - + base::TimeDelta::FromMilliseconds(2)); PressKey(ui::VKEY_VOLUME_DOWN); // Verifies screenshot is taken, volume down is consumed. EXPECT_EQ(1, GetScreenshotCount()); EXPECT_TRUE(LastKeyConsumed()); // Keeps pressing volume down key under screenshot chord condition will not // take screenshot again, volume down is also consumed. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); ResetScreenshotCount(); PressKey(ui::VKEY_VOLUME_DOWN); EXPECT_EQ(0, GetScreenshotCount()); EXPECT_TRUE(LastKeyConsumed()); // Keeps pressing volume down key off screenshot chord condition will not // take screenshot and still consume volume down event. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(2)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2)); PressKey(ui::VKEY_VOLUME_DOWN); EXPECT_EQ(0, GetScreenshotCount()); EXPECT_TRUE(LastKeyConsumed()); @@ -161,14 +161,14 @@ TEST_F(PowerButtonScreenshotControllerTest, PowerButtonPressedFirst_NoScreenshotChord) { PressPowerButton(); - tick_clock_->Advance(PowerButtonScreenshotController::kScreenshotChordDelay + - base::TimeDelta::FromMilliseconds(1)); + tick_clock_.Advance(PowerButtonScreenshotController::kScreenshotChordDelay + + base::TimeDelta::FromMilliseconds(1)); PressKey(ui::VKEY_VOLUME_DOWN); // Verifies screenshot is not taken, volume down is not consumed. EXPECT_EQ(0, GetScreenshotCount()); EXPECT_FALSE(LastKeyConsumed()); // Keeps pressing volume down key should continue triggerring volume down. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(2)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2)); PressKey(ui::VKEY_VOLUME_DOWN); EXPECT_EQ(0, GetScreenshotCount()); EXPECT_FALSE(LastKeyConsumed()); @@ -238,20 +238,20 @@ EXPECT_TRUE(LastKeyConsumed()); // Presses power button under screenshot chord condition, and verifies that // screenshot is taken. - tick_clock_->Advance(PowerButtonScreenshotController::kScreenshotChordDelay - - base::TimeDelta::FromMilliseconds(2)); + tick_clock_.Advance(PowerButtonScreenshotController::kScreenshotChordDelay - + base::TimeDelta::FromMilliseconds(2)); PressPowerButton(); EXPECT_EQ(1, GetScreenshotCount()); // Keeps pressing volume down key under screenshot chord condition will not // take screenshot again, volume down is also consumed. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); ResetScreenshotCount(); PressKey(ui::VKEY_VOLUME_DOWN); EXPECT_EQ(0, GetScreenshotCount()); EXPECT_TRUE(LastKeyConsumed()); // Keeps pressing volume down key off screenshot chord condition will not take // screenshot and still consume volume down event. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(2)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2)); PressKey(ui::VKEY_VOLUME_DOWN); EXPECT_EQ(0, GetScreenshotCount()); EXPECT_TRUE(LastKeyConsumed()); @@ -276,14 +276,14 @@ // Advances |tick_clock_| to off screenshot chord point. This will also // trigger volume down timer timeout, which will perform a volume down // operation. - tick_clock_->Advance(PowerButtonScreenshotController::kScreenshotChordDelay + - base::TimeDelta::FromMilliseconds(1)); + tick_clock_.Advance(PowerButtonScreenshotController::kScreenshotChordDelay + + base::TimeDelta::FromMilliseconds(1)); EXPECT_TRUE(screenshot_test_api_->TriggerVolumeDownTimer()); // Presses power button would not take screenshot. PressPowerButton(); EXPECT_EQ(0, GetScreenshotCount()); // Keeps pressing volume down key should continue triggerring volume down. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(2)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2)); PressKey(ui::VKEY_VOLUME_DOWN); EXPECT_EQ(0, GetScreenshotCount()); EXPECT_FALSE(LastKeyConsumed()); @@ -379,8 +379,8 @@ // Tests volume down key stops clamshell power button timer. PressPowerButton(); EXPECT_TRUE(screenshot_test_api_->ClamshellPowerButtonTimerIsRunning()); - tick_clock_->Advance(PowerButtonScreenshotController::kScreenshotChordDelay - - base::TimeDelta::FromMilliseconds(1)); + tick_clock_.Advance(PowerButtonScreenshotController::kScreenshotChordDelay - + base::TimeDelta::FromMilliseconds(1)); PressKey(ui::VKEY_VOLUME_DOWN); // Under screenshot chord condition, screenshot is taken and volume down key // pressed is consumed.
diff --git a/ash/system/power/power_button_test_base.cc b/ash/system/power/power_button_test_base.cc index 3cd11ad..3a10e9a 100644 --- a/ash/system/power/power_button_test_base.cc +++ b/ash/system/power/power_button_test_base.cc
@@ -67,9 +67,7 @@ void PowerButtonTestBase::InitPowerButtonControllerMembers( chromeos::PowerManagerClient::TabletMode initial_tablet_mode_switch_state) { power_button_controller_ = Shell::Get()->power_button_controller(); - tick_clock_ = new base::SimpleTestTickClock; - power_button_controller_->SetTickClockForTesting( - base::WrapUnique(tick_clock_)); + power_button_controller_->SetTickClockForTesting(&tick_clock_); if (initial_tablet_mode_switch_state != chromeos::PowerManagerClient::TabletMode::UNSUPPORTED) { @@ -108,12 +106,12 @@ void PowerButtonTestBase::PressPowerButton() { power_button_controller_->PowerButtonEventReceived(true, - tick_clock_->NowTicks()); + tick_clock_.NowTicks()); } void PowerButtonTestBase::ReleasePowerButton() { power_button_controller_->PowerButtonEventReceived(false, - tick_clock_->NowTicks()); + tick_clock_.NowTicks()); } void PowerButtonTestBase::PressKey(ui::KeyboardCode key_code) { @@ -156,7 +154,7 @@ } void PowerButtonTestBase::AdvanceClockToAvoidIgnoring() { - tick_clock_->Advance( + tick_clock_.Advance( TabletPowerButtonController::kIgnoreRepeatedButtonUpDelay + base::TimeDelta::FromMilliseconds(1)); }
diff --git a/ash/system/power/power_button_test_base.h b/ash/system/power/power_button_test_base.h index 04ad5e5e..860fb41 100644 --- a/ash/system/power/power_button_test_base.h +++ b/ash/system/power/power_button_test_base.h
@@ -10,12 +10,9 @@ #include "ash/system/power/power_button_controller.h" #include "ash/system/power/tablet_power_button_controller.h" #include "ash/test/ash_test_base.h" +#include "base/test/simple_test_tick_clock.h" #include "ui/events/keycodes/keyboard_codes_posix.h" -namespace base { -class SimpleTestTickClock; -} // namespace base - namespace chromeos { class FakePowerManagerClient; class FakeSessionManagerClient; @@ -114,7 +111,7 @@ nullptr; // Not owned. std::unique_ptr<LockStateControllerTestApi> lock_state_test_api_; std::unique_ptr<TabletPowerButtonControllerTestApi> tablet_test_api_; - base::SimpleTestTickClock* tick_clock_ = nullptr; // Not owned. + base::SimpleTestTickClock tick_clock_; // Indicates whether switches::kAshEnableTabletMode is appended. bool has_tablet_mode_switch_ = true;
diff --git a/ash/system/power/tablet_power_button_controller_unittest.cc b/ash/system/power/tablet_power_button_controller_unittest.cc index 4b62604..7131b7ce 100644 --- a/ash/system/power/tablet_power_button_controller_unittest.cc +++ b/ash/system/power/tablet_power_button_controller_unittest.cc
@@ -48,7 +48,7 @@ // Advance a duration longer than |kIgnorePowerButtonAfterResumeDelay| to // avoid events being ignored. - tick_clock_->Advance( + tick_clock_.Advance( TabletPowerButtonController::kIgnorePowerButtonAfterResumeDelay + base::TimeDelta::FromMilliseconds(2)); @@ -174,7 +174,7 @@ // Send the power button event after a short delay and check that backlights // are not forced off. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(500)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(500)); PressPowerButton(); EXPECT_TRUE(tablet_test_api_->ShutdownTimerIsRunning()); ReleasePowerButton(); @@ -183,7 +183,7 @@ // Send the power button event after a longer delay and check that backlights // are forced off. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1600)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1600)); PressPowerButton(); EXPECT_TRUE(tablet_test_api_->ShutdownTimerIsRunning()); ReleasePowerButton(); @@ -209,7 +209,7 @@ // Send the power button event after a short delay and check that backlights // are not forced off. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(500)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(500)); PressPowerButton(); power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true); EXPECT_TRUE(tablet_test_api_->ShutdownTimerIsRunning()); @@ -219,7 +219,7 @@ // Send the power button event after a longer delay and check that backlights // are forced off. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1600)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1600)); PressPowerButton(); EXPECT_TRUE(tablet_test_api_->ShutdownTimerIsRunning()); ReleasePowerButton(); @@ -373,7 +373,7 @@ EXPECT_TRUE(tablet_test_api_->ShutdownTimerIsRunning()); tablet_controller_->OnTabletModeStarted(); EXPECT_FALSE(tablet_test_api_->ShutdownTimerIsRunning()); - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1500)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1500)); ReleasePowerButton(); EXPECT_FALSE(GetLockedState()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); @@ -383,7 +383,7 @@ EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running()); tablet_controller_->OnTabletModeStarted(); EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running()); - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(2500)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2500)); ReleasePowerButton(); EXPECT_FALSE(GetLockedState()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); @@ -392,7 +392,7 @@ EXPECT_TRUE(tablet_test_api_->ShutdownTimerIsRunning()); tablet_controller_->OnTabletModeEnded(); EXPECT_FALSE(tablet_test_api_->ShutdownTimerIsRunning()); - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(3500)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(3500)); ReleasePowerButton(); EXPECT_FALSE(GetLockedState()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); @@ -402,7 +402,7 @@ EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running()); tablet_controller_->OnTabletModeEnded(); EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running()); - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(4500)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(4500)); ReleasePowerButton(); EXPECT_FALSE(GetLockedState()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); @@ -418,7 +418,7 @@ // Test that a pressing-releasing operation after a short duration, backlights // forced off is stopped since we don't drop request for power button pressed. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(200)); PressPowerButton(); power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true); ReleasePowerButton(); @@ -426,13 +426,13 @@ // Test that after another short duration, backlights will not be forced off // since this immediately following forcing off request needs to be dropped. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(200)); PressPowerButton(); ReleasePowerButton(); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); // Test that after another long duration, backlights should be forced off. - tick_clock_->Advance(base::TimeDelta::FromMilliseconds(800)); + tick_clock_.Advance(base::TimeDelta::FromMilliseconds(800)); PressPowerButton(); ReleasePowerButton(); power_manager_client_->SendBrightnessChanged(0, true); @@ -448,7 +448,7 @@ // A lid closed event is received, we should stop forcing off backlights. power_manager_client_->SetLidState(PowerManagerClient::LidState::CLOSED, - tick_clock_->NowTicks()); + tick_clock_.NowTicks()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); // Pressing/releasing power button again to set backlights forced off. This is @@ -461,7 +461,7 @@ // A lid open event is received, we should stop forcing off backlights. power_manager_client_->SetLidState(PowerManagerClient::LidState::OPEN, - tick_clock_->NowTicks()); + tick_clock_.NowTicks()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); } @@ -471,7 +471,7 @@ ReleasePowerButton(); ASSERT_TRUE(power_manager_client_->backlights_forced_off()); power_manager_client_->SetTabletMode(PowerManagerClient::TabletMode::ON, - tick_clock_->NowTicks()); + tick_clock_.NowTicks()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); AdvanceClockToAvoidIgnoring(); @@ -479,7 +479,7 @@ ReleasePowerButton(); ASSERT_TRUE(power_manager_client_->backlights_forced_off()); power_manager_client_->SetTabletMode(PowerManagerClient::TabletMode::OFF, - tick_clock_->NowTicks()); + tick_clock_.NowTicks()); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); } @@ -637,8 +637,8 @@ EXPECT_FALSE(power_manager_client_->backlights_forced_off()); // Since display could still be off, ignore forcing off. - tick_clock_->Advance(TabletPowerButtonController::kScreenStateChangeDelay - - base::TimeDelta::FromMilliseconds(1)); + tick_clock_.Advance(TabletPowerButtonController::kScreenStateChangeDelay - + base::TimeDelta::FromMilliseconds(1)); PressPowerButton(); ReleasePowerButton(); EXPECT_FALSE(power_manager_client_->backlights_forced_off()); @@ -687,7 +687,7 @@ // Advance a duration longer than |kIgnorePowerButtonAfterResumeDelay| to // avoid events being ignored. - tick_clock_->Advance( + tick_clock_.Advance( TabletPowerButtonController::kIgnorePowerButtonAfterResumeDelay + base::TimeDelta::FromMilliseconds(2)); }
diff --git a/ash/system/session/logout_confirmation_controller.cc b/ash/system/session/logout_confirmation_controller.cc index 611e936d..7e8f416 100644 --- a/ash/system/session/logout_confirmation_controller.cc +++ b/ash/system/session/logout_confirmation_controller.cc
@@ -109,7 +109,7 @@ }; LogoutConfirmationController::LogoutConfirmationController() - : clock_(std::make_unique<base::DefaultTickClock>()), + : clock_(base::DefaultTickClock::GetInstance()), logout_closure_(base::Bind(&SignOut)), logout_timer_(false, false), scoped_session_observer_(this) {} @@ -171,9 +171,8 @@ logout_timer_.Stop(); } -void LogoutConfirmationController::SetClockForTesting( - std::unique_ptr<base::TickClock> clock) { - clock_ = std::move(clock); +void LogoutConfirmationController::SetClockForTesting(base::TickClock* clock) { + clock_ = clock; } void LogoutConfirmationController::SetLogoutClosureForTesting(
diff --git a/ash/system/session/logout_confirmation_controller.h b/ash/system/session/logout_confirmation_controller.h index b94affc..eccb07d 100644 --- a/ash/system/session/logout_confirmation_controller.h +++ b/ash/system/session/logout_confirmation_controller.h
@@ -37,7 +37,7 @@ LogoutConfirmationController(); ~LogoutConfirmationController() override; - base::TickClock* clock() const { return clock_.get(); } + base::TickClock* clock() const { return clock_; } // Shows a LogoutConfirmationDialog. If a confirmation dialog is already being // shown, it is closed and a new one opened if |logout_time| is earlier than @@ -54,7 +54,10 @@ // Called by the |dialog_| when it is closed. void OnDialogClosed(); - void SetClockForTesting(std::unique_ptr<base::TickClock> clock); + // Overrides the internal clock for testing. This doesn't take the ownership + // of the clock. |clock| must outlive the LogoutConfirmationController + // instance. + void SetClockForTesting(base::TickClock* clock); void SetLogoutClosureForTesting(const base::Closure& logout_closure); LogoutConfirmationDialog* dialog_for_testing() const { return dialog_; } @@ -62,7 +65,7 @@ class LastWindowClosedObserver; std::unique_ptr<LastWindowClosedObserver> last_window_closed_observer_; - std::unique_ptr<base::TickClock> clock_; + base::TickClock* clock_; base::Closure logout_closure_; base::TimeTicks logout_time_;
diff --git a/ash/system/session/logout_confirmation_controller_unittest.cc b/ash/system/session/logout_confirmation_controller_unittest.cc index c69575e..1c9b77f 100644 --- a/ash/system/session/logout_confirmation_controller_unittest.cc +++ b/ash/system/session/logout_confirmation_controller_unittest.cc
@@ -33,6 +33,10 @@ scoped_refptr<base::TestMockTimeTaskRunner> runner_; base::ThreadTaskRunnerHandle runner_handle_; + // TODO(tzik): Remove |tick_clock_| after updating GetMockTickClock to own the + // instance. + std::unique_ptr<base::TickClock> tick_clock_; + LogoutConfirmationController controller_; private: @@ -42,8 +46,9 @@ LogoutConfirmationControllerTest::LogoutConfirmationControllerTest() : log_out_called_(false), runner_(new base::TestMockTimeTaskRunner), - runner_handle_(runner_) { - controller_.SetClockForTesting(runner_->GetMockTickClock()); + runner_handle_(runner_), + tick_clock_(runner_->GetMockTickClock()) { + controller_.SetClockForTesting(tick_clock_.get()); controller_.SetLogoutClosureForTesting(base::Bind( &LogoutConfirmationControllerTest::LogOut, base::Unretained(this))); }
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc index d8f6b5d..e383641 100644 --- a/ash/system/status_area_widget.cc +++ b/ash/system/status_area_widget.cc
@@ -4,6 +4,7 @@ #include "ash/system/status_area_widget.h" +#include "ash/public/cpp/ash_features.h" #include "ash/session/session_controller.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" @@ -14,6 +15,7 @@ #include "ash/system/session/logout_button_tray.h" #include "ash/system/status_area_widget_delegate.h" #include "ash/system/tray/system_tray.h" +#include "ash/system/unified/unified_system_tray.h" #include "ash/system/virtual_keyboard/virtual_keyboard_tray.h" #include "ash/system/web_notification/web_notification_tray.h" #include "base/i18n/time_formatting.h" @@ -47,6 +49,11 @@ system_tray_ = std::make_unique<SystemTray>(shelf_); status_area_widget_delegate_->AddChildView(system_tray_.get()); + if (features::IsSystemTrayUnifiedEnabled()) { + system_tray_unified_ = std::make_unique<UnifiedSystemTray>(shelf_); + status_area_widget_delegate_->AddChildView(system_tray_unified_.get()); + } + // Must happen after the widget is initialized so the native window exists. web_notification_tray_ = std::make_unique<WebNotificationTray>( shelf_, GetNativeWindow(), system_tray_.get()); @@ -92,6 +99,7 @@ web_notification_tray_.reset(); // Must be destroyed after |web_notification_tray_|. system_tray_.reset(); + system_tray_unified_.reset(); ime_menu_tray_.reset(); virtual_keyboard_tray_.reset(); palette_tray_.reset();
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h index 958b34d..955f28f 100644 --- a/ash/system/status_area_widget.h +++ b/ash/system/status_area_widget.h
@@ -25,6 +25,7 @@ class Shelf; class StatusAreaWidgetDelegate; class SystemTray; +class UnifiedSystemTray; class TrayBackgroundView; class VirtualKeyboardTray; class WebNotificationTray; @@ -65,6 +66,9 @@ return status_area_widget_delegate_; } SystemTray* system_tray() { return system_tray_.get(); } + UnifiedSystemTray* system_tray_unified() { + return system_tray_unified_.get(); + } WebNotificationTray* web_notification_tray() { return web_notification_tray_.get(); } @@ -113,6 +117,7 @@ std::unique_ptr<OverviewButtonTray> overview_button_tray_; std::unique_ptr<SystemTray> system_tray_; + std::unique_ptr<UnifiedSystemTray> system_tray_unified_; std::unique_ptr<WebNotificationTray> web_notification_tray_; std::unique_ptr<LogoutButtonTray> logout_button_tray_; std::unique_ptr<PaletteTray> palette_tray_;
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index be5e346..7df970f 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc
@@ -12,6 +12,7 @@ #include "ash/accessibility/accessibility_controller.h" #include "ash/login_status.h" #include "ash/metrics/user_metrics_recorder.h" +#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/shell_window_ids.h" @@ -41,6 +42,7 @@ #include "ash/system/screen_security/screen_share_tray_item.h" #include "ash/system/screen_security/screen_tray_item.h" #include "ash/system/session/tray_session_length_limit.h" +#include "ash/system/status_area_widget.h" #include "ash/system/supervised/tray_supervised_user.h" #include "ash/system/tiles/tray_tiles.h" #include "ash/system/tray/system_tray_controller.h" @@ -51,6 +53,7 @@ #include "ash/system/tray_accessibility.h" #include "ash/system/tray_caps_lock.h" #include "ash/system/tray_tracing.h" +#include "ash/system/unified/unified_system_tray.h" #include "ash/system/update/tray_update.h" #include "ash/system/user/tray_user.h" #include "ash/system/web_notification/web_notification_tray.h" @@ -577,6 +580,11 @@ UserMetricsRecorder::RecordUserClickOnTray( LoginMetricsRecorder::TrayClickTarget::kSystemTray); + if (features::IsSystemTrayUnifiedEnabled()) { + return shelf()->GetStatusAreaWidget()->system_tray_unified()->PerformAction( + event); + } + // If we're already showing a full system tray menu, either default or // detailed menu, hide it; otherwise, show it (and hide any popup that's // currently shown).
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h index 1886adb..8098deb 100644 --- a/ash/system/tray/tray_constants.h +++ b/ash/system/tray/tray_constants.h
@@ -129,6 +129,10 @@ constexpr SkColor kUnifiedMenuIconColor = SkColorSetRGB(0xf1, 0xf2, 0xf3); constexpr SkColor kUnifiedMenuIconColorDisabled = SkColorSetA(kUnifiedMenuIconColor, 0xa3); +constexpr SkColor kUnifiedMenuButtonColor = + SkColorSetA(kUnifiedMenuIconColor, 0x14); + +constexpr int kUnifiedTopShortcutSpacing = 16; } // namespace ash
diff --git a/ash/system/unified/top_shortcut_button.cc b/ash/system/unified/top_shortcut_button.cc new file mode 100644 index 0000000..feab131 --- /dev/null +++ b/ash/system/unified/top_shortcut_button.cc
@@ -0,0 +1,72 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/unified/top_shortcut_button.h" + +#include "ash/system/tray/tray_constants.h" +#include "ash/system/tray/tray_popup_utils.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/animation/flood_fill_ink_drop_ripple.h" +#include "ui/views/animation/ink_drop_highlight.h" +#include "ui/views/animation/ink_drop_impl.h" +#include "ui/views/animation/ink_drop_mask.h" + +namespace ash { + +TopShortcutButton::TopShortcutButton(views::ButtonListener* listener, + const gfx::VectorIcon& icon, + int accessible_name_id) + : views::ImageButton(listener) { + SetPreferredSize(gfx::Size(kTrayItemSize, kTrayItemSize)); + + SetImage(views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(icon, kUnifiedMenuIconColor)); + SetImage(views::Button::STATE_DISABLED, + gfx::CreateVectorIcon(icon, kUnifiedMenuIconColorDisabled)); + + SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE); + SetTooltipText(l10n_util::GetStringUTF16(accessible_name_id)); + + TrayPopupUtils::ConfigureTrayPopupButton(this); +} + +TopShortcutButton::~TopShortcutButton() = default; + +void TopShortcutButton::PaintButtonContents(gfx::Canvas* canvas) { + gfx::Rect rect(GetContentsBounds()); + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setColor(kUnifiedMenuButtonColor); + flags.setStyle(cc::PaintFlags::kFill_Style); + canvas->DrawCircle(gfx::PointF(rect.CenterPoint()), kTrayItemSize / 2, flags); + + views::ImageButton::PaintButtonContents(canvas); +} + +std::unique_ptr<views::InkDrop> TopShortcutButton::CreateInkDrop() { + return TrayPopupUtils::CreateInkDrop(this); +} + +std::unique_ptr<views::InkDropRipple> TopShortcutButton::CreateInkDropRipple() + const { + return TrayPopupUtils::CreateInkDropRipple( + TrayPopupInkDropStyle::FILL_BOUNDS, this, + GetInkDropCenterBasedOnLastEvent(), kUnifiedMenuIconColor); +} + +std::unique_ptr<views::InkDropHighlight> +TopShortcutButton::CreateInkDropHighlight() const { + return TrayPopupUtils::CreateInkDropHighlight( + TrayPopupInkDropStyle::FILL_BOUNDS, this, kUnifiedMenuIconColor); +} + +std::unique_ptr<views::InkDropMask> TopShortcutButton::CreateInkDropMask() + const { + return std::make_unique<views::CircleInkDropMask>( + size(), GetContentsBounds().CenterPoint(), kTrayItemSize / 2); +} + +} // namespace ash
diff --git a/ash/system/unified/top_shortcut_button.h b/ash/system/unified/top_shortcut_button.h new file mode 100644 index 0000000..aac6e6c --- /dev/null +++ b/ash/system/unified/top_shortcut_button.h
@@ -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. + +#ifndef ASH_SYSTEM_UNIFIED_TOP_SHORTCUT_BUTTON_H_ +#define ASH_SYSTEM_UNIFIED_TOP_SHORTCUT_BUTTON_H_ + +#include "ui/gfx/vector_icon_types.h" +#include "ui/views/controls/button/image_button.h" + +namespace ash { + +// A button used in top shortcuts. Top shortcuts are small circular buttons +// shown on top of the UnifiedSystemTrayView that allows quick access to +// frequently used features e.g. lock screen, settings, and shutdown. +class TopShortcutButton : public views::ImageButton { + public: + TopShortcutButton(views::ButtonListener* listener, + const gfx::VectorIcon& icon, + int accessible_name_id); + ~TopShortcutButton() override; + + // views::ImageButton: + void PaintButtonContents(gfx::Canvas* canvas) override; + std::unique_ptr<views::InkDrop> CreateInkDrop() override; + std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; + std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() + const override; + std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(TopShortcutButton); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_TOP_SHORTCUT_BUTTON_H_
diff --git a/ash/system/unified/top_shortcuts_view.cc b/ash/system/unified/top_shortcuts_view.cc new file mode 100644 index 0000000..a47398b --- /dev/null +++ b/ash/system/unified/top_shortcuts_view.cc
@@ -0,0 +1,63 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/unified/top_shortcuts_view.h" + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/session/session_controller.h" +#include "ash/shell.h" +#include "ash/shutdown_controller.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/system/tray/tray_constants.h" +#include "ash/system/tray/tray_popup_utils.h" +#include "ash/system/unified/top_shortcut_button.h" +#include "ash/system/unified/unified_system_tray_controller.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +TopShortcutsView::TopShortcutsView(UnifiedSystemTrayController* controller) + : controller_(controller) { + DCHECK(controller_); + + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(kUnifiedTopShortcutSpacing), + kUnifiedTopShortcutSpacing)); + + // Show the buttons in this row as disabled if the user is at the login + // screen, lock screen, or in a secondary account flow. The exception is + // |power_button_| which is always shown as enabled. + const bool can_show_web_ui = TrayPopupUtils::CanOpenWebUISettings(); + + lock_button_ = new TopShortcutButton(this, kSystemMenuLockIcon, + IDS_ASH_STATUS_TRAY_LOCK); + lock_button_->SetEnabled(can_show_web_ui && + Shell::Get()->session_controller()->CanLockScreen()); + AddChildView(lock_button_); + + settings_button_ = new TopShortcutButton(this, kSystemMenuSettingsIcon, + IDS_ASH_STATUS_TRAY_SETTINGS); + settings_button_->SetEnabled(can_show_web_ui); + AddChildView(settings_button_); + + bool reboot = Shell::Get()->shutdown_controller()->reboot_on_shutdown(); + power_button_ = new TopShortcutButton( + this, kSystemMenuPowerIcon, + reboot ? IDS_ASH_STATUS_TRAY_REBOOT : IDS_ASH_STATUS_TRAY_SHUTDOWN); + AddChildView(power_button_); +} + +TopShortcutsView::~TopShortcutsView() = default; + +void TopShortcutsView::ButtonPressed(views::Button* sender, + const ui::Event& event) { + if (sender == lock_button_) + controller_->HandleLockAction(); + else if (sender == settings_button_) + controller_->HandleSettingsAction(); + else if (sender == power_button_) + controller_->HandlePowerAction(); +} + +} // namespace ash
diff --git a/ash/system/unified/top_shortcuts_view.h b/ash/system/unified/top_shortcuts_view.h new file mode 100644 index 0000000..928909fd --- /dev/null +++ b/ash/system/unified/top_shortcuts_view.h
@@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_UNIFIED_TOP_SHORTCUTS_VIEW_H_ +#define ASH_SYSTEM_UNIFIED_TOP_SHORTCUTS_VIEW_H_ + +#include "ui/views/controls/button/button.h" +#include "ui/views/view.h" + +namespace ash { + +class UnifiedSystemTrayController; +class TopShortcutButton; + +// Top shortcuts view shown on the top of UnifiedSystemTrayView. +class TopShortcutsView : public views::View, public views::ButtonListener { + public: + explicit TopShortcutsView(UnifiedSystemTrayController* controller); + ~TopShortcutsView() override; + + // views::ButtonListener: + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + private: + UnifiedSystemTrayController* controller_; + + // Owned by views hierarchy. + TopShortcutButton* lock_button_ = nullptr; + TopShortcutButton* settings_button_ = nullptr; + TopShortcutButton* power_button_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(TopShortcutsView); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_TOP_SHORTCUTS_VIEW_H_
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc new file mode 100644 index 0000000..07437aed --- /dev/null +++ b/ash/system/unified/unified_system_tray.cc
@@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/unified/unified_system_tray.h" + +#include "ash/system/status_area_widget.h" +#include "ash/system/tray/system_tray.h" +#include "ash/system/unified/unified_system_tray_bubble.h" + +namespace ash { + +UnifiedSystemTray::UnifiedSystemTray(Shelf* shelf) : TrayBackgroundView(shelf) { + // On the first step, features in the status area button are still provided by + // TrayViews in SystemTray. + // TODO(tetsui): Remove SystemTray from StatusAreaWidget and provide these + // features from UnifiedSystemTray. + SetVisible(false); +} + +UnifiedSystemTray::~UnifiedSystemTray() = default; + +bool UnifiedSystemTray::PerformAction(const ui::Event& event) { + if (bubble_) + CloseBubble(); + else + ShowBubble(true /* show_by_click */); + return true; +} + +void UnifiedSystemTray::ShowBubble(bool show_by_click) { + bubble_ = std::make_unique<UnifiedSystemTrayBubble>(this); + // TODO(tetsui): Call its own SetIsActive. See the comment in the ctor. + shelf()->GetStatusAreaWidget()->system_tray()->SetIsActive(true); +} + +void UnifiedSystemTray::CloseBubble() { + bubble_.reset(); + // TODO(tetsui): Call its own SetIsActive. See the comment in the ctor. + shelf()->GetStatusAreaWidget()->system_tray()->SetIsActive(false); +} + +base::string16 UnifiedSystemTray::GetAccessibleNameForTray() { + // TODO(tetsui): Implement. + return base::string16(); +} + +void UnifiedSystemTray::HideBubbleWithView( + const views::TrayBubbleView* bubble_view) {} + +void UnifiedSystemTray::ClickedOutsideBubble() {} + +} // namespace ash
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h new file mode 100644 index 0000000..69a04328 --- /dev/null +++ b/ash/system/unified/unified_system_tray.h
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_H_ +#define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_H_ + +#include <memory> + +#include "ash/system/tray/tray_background_view.h" + +namespace ash { + +class UnifiedSystemTrayBubble; + +// UnifiedSystemTray is system menu of Chromium OS, which is typically +// accessible from the button on the right bottom of the screen (Status Area). +// The button shows multiple icons on it to indicate system status. +// UnifiedSystemTrayBubble is the actual menu bubble shown on top of it when the +// button is clicked. +// +// UnifiedSystemTray is the view class of that button. It creates and owns +// UnifiedSystemTrayBubble when it is clicked. +// +// UnifiedSystemTray is alternative implementation of SystemTray that is going +// to replace the original one. Eventually, SystemTray will be removed. +// During the transition, we hide UnifiedSystemTray button and forward +// PerformAction() from SystemTray button, as we still don't have implementation +// of status icons on the UnifiedSystemTray button. +class UnifiedSystemTray : public TrayBackgroundView { + public: + explicit UnifiedSystemTray(Shelf* shelf); + ~UnifiedSystemTray() override; + + // TrayBackgroundView: + bool PerformAction(const ui::Event& event) override; + void ShowBubble(bool show_by_click) override; + void CloseBubble() override; + base::string16 GetAccessibleNameForTray() override; + void HideBubbleWithView(const views::TrayBubbleView* bubble_view) override; + void ClickedOutsideBubble() override; + + private: + std::unique_ptr<UnifiedSystemTrayBubble> bubble_; + + DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTray); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_H_
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc new file mode 100644 index 0000000..3393506 --- /dev/null +++ b/ash/system/unified/unified_system_tray_bubble.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/system/unified/unified_system_tray_bubble.h" + +#include "ash/system/tray/tray_constants.h" +#include "ash/system/unified/unified_system_tray.h" +#include "ash/system/unified/unified_system_tray_controller.h" +#include "ash/system/unified/unified_system_tray_view.h" + +namespace ash { + +UnifiedSystemTrayBubble::UnifiedSystemTrayBubble(UnifiedSystemTray* tray) + : controller_(std::make_unique<UnifiedSystemTrayController>()), + tray_(tray) { + views::TrayBubbleView::InitParams init_params; + init_params.anchor_alignment = views::TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM; + init_params.min_width = kTrayMenuWidth; + init_params.max_width = kTrayMenuWidth; + init_params.delegate = tray; + init_params.parent_window = tray->GetBubbleWindowContainer(); + init_params.anchor_view = + tray->shelf()->GetSystemTrayAnchor()->GetBubbleAnchor(); + + auto* bubble_view = new views::TrayBubbleView(init_params); + bubble_view->AddChildView(controller_->CreateView()); + bubble_view->set_anchor_view_insets( + tray->shelf()->GetSystemTrayAnchor()->GetBubbleAnchorInsets()); + bubble_view->set_color(kUnifiedMenuBackgroundColor); + + bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view); + bubble_widget_->AddObserver(this); + + TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); + bubble_view->InitializeAndShowBubble(); + + bubble_widget_->widget_delegate()->set_can_activate(true); + bubble_widget_->Activate(); +} + +UnifiedSystemTrayBubble::~UnifiedSystemTrayBubble() { + if (bubble_widget_) { + bubble_widget_->RemoveObserver(this); + bubble_widget_->Close(); + } +} + +void UnifiedSystemTrayBubble::OnWidgetDestroying(views::Widget* widget) { + CHECK_EQ(bubble_widget_, widget); + bubble_widget_->RemoveObserver(this); + bubble_widget_ = nullptr; + tray_->CloseBubble(); +} + +} // namespace ash
diff --git a/ash/system/unified/unified_system_tray_bubble.h b/ash/system/unified/unified_system_tray_bubble.h new file mode 100644 index 0000000..9e9a32d --- /dev/null +++ b/ash/system/unified/unified_system_tray_bubble.h
@@ -0,0 +1,54 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_BUBBLE_H_ +#define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_BUBBLE_H_ + +#include <memory> + +#include "base/macros.h" +#include "ui/views/widget/widget_observer.h" + +namespace views { +class Widget; +} + +namespace ash { + +class UnifiedSystemTray; +class UnifiedSystemTrayController; + +// Manages the bubble that contains UnifiedSystemTrayView. +// Shows the bubble on the constructor, and closes the bubble on the destructor. +// It is possible that the bubble widget is closed on deactivation. In such +// case, this class calls UnifiedSystemTray::CloseBubble() to delete itself. +class UnifiedSystemTrayBubble : public views::WidgetObserver { + public: + explicit UnifiedSystemTrayBubble(UnifiedSystemTray* tray); + ~UnifiedSystemTrayBubble() override; + + // views::WidgetObserver: + void OnWidgetDestroying(views::Widget* widget) override; + + private: + // Controller of UnifiedSystemTrayView. As the view is owned by views + // hierarchy, we have to own the controller here. + std::unique_ptr<UnifiedSystemTrayController> controller_; + + // Owner of this class. + UnifiedSystemTray* tray_; + + // Widget that contains UnifiedSystemTrayView. Unowned. + // When the widget is closed by deactivation, |bubble_widget_| pointer is + // invalidated and we have to delete UnifiedSystemTrayBubble by calling + // UnifiedSystemTray::CloseBubble(). + // In order to do this, we observe OnWidgetDestroying(). + views::Widget* bubble_widget_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTrayBubble); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_BUBBLE_H_
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc new file mode 100644 index 0000000..3f93cc0 --- /dev/null +++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -0,0 +1,46 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/unified/unified_system_tray_controller.h" + +#include "ash/metrics/user_metrics_action.h" +#include "ash/metrics/user_metrics_recorder.h" +#include "ash/shell.h" +#include "ash/system/tray/system_tray_controller.h" +#include "ash/system/unified/unified_system_tray_view.h" +#include "ash/wm/lock_state_controller.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/session_manager_client.h" + +namespace ash { + +UnifiedSystemTrayController::UnifiedSystemTrayController() = default; + +UnifiedSystemTrayController::~UnifiedSystemTrayController() = default; + +UnifiedSystemTrayView* UnifiedSystemTrayController::CreateView() { + DCHECK(!unified_view_); + unified_view_ = new UnifiedSystemTrayView(this); + return unified_view_; +} + +void UnifiedSystemTrayController::HandleLockAction() { + Shell::Get()->metrics()->RecordUserMetricsAction(UMA_TRAY_LOCK_SCREEN); + chromeos::DBusThreadManager::Get() + ->GetSessionManagerClient() + ->RequestLockScreen(); +} + +void UnifiedSystemTrayController::HandleSettingsAction() { + Shell::Get()->metrics()->RecordUserMetricsAction(UMA_TRAY_SETTINGS); + Shell::Get()->system_tray_controller()->ShowSettings(); +} + +void UnifiedSystemTrayController::HandlePowerAction() { + Shell::Get()->metrics()->RecordUserMetricsAction(UMA_TRAY_SHUT_DOWN); + Shell::Get()->lock_state_controller()->RequestShutdown( + ShutdownReason::TRAY_SHUT_DOWN_BUTTON); +} + +} // namespace ash
diff --git a/ash/system/unified/unified_system_tray_controller.h b/ash/system/unified/unified_system_tray_controller.h new file mode 100644 index 0000000..25ef94c --- /dev/null +++ b/ash/system/unified/unified_system_tray_controller.h
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_CONTROLLER_H_ +#define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_CONTROLLER_H_ + +#include "base/macros.h" + +namespace ash { + +class UnifiedSystemTrayView; + +// Controller class of UnifiedSystemTrayView. Handles events of the view. +class UnifiedSystemTrayController { + public: + UnifiedSystemTrayController(); + ~UnifiedSystemTrayController(); + + // Create the view. The created view is unowned. + UnifiedSystemTrayView* CreateView(); + + // Show lock screen which asks the user password. Called from the view. + void HandleLockAction(); + // Show WebUI settings. Called from the view. + void HandleSettingsAction(); + // Shutdown the computer. Called from the view. + void HandlePowerAction(); + + private: + // Unowned. Owned by Views hierarchy. + UnifiedSystemTrayView* unified_view_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTrayController); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_CONTROLLER_H_
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc new file mode 100644 index 0000000..1c8f441 --- /dev/null +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/unified/unified_system_tray_view.h" + +#include "ash/system/unified/top_shortcuts_view.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +UnifiedSystemTrayView::UnifiedSystemTrayView( + UnifiedSystemTrayController* controller) + : controller_(controller) { + DCHECK(controller_); + + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); + + AddChildView(new TopShortcutsView(controller_)); +} + +UnifiedSystemTrayView::~UnifiedSystemTrayView() = default; + +} // namespace ash
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h new file mode 100644 index 0000000..4ba2087e --- /dev/null +++ b/ash/system/unified/unified_system_tray_view.h
@@ -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. + +#ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_VIEW_H_ +#define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_VIEW_H_ + +#include "ui/views/view.h" + +namespace ash { + +class UnifiedSystemTrayController; + +// View class of default view in UnifiedSystemTray. +class UnifiedSystemTrayView : public views::View { + public: + explicit UnifiedSystemTrayView(UnifiedSystemTrayController* controller); + ~UnifiedSystemTrayView() override; + + private: + UnifiedSystemTrayController* controller_; + + DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTrayView); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_VIEW_H_
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 481b8c50..a009cd3a 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -763,20 +763,20 @@ } bool WallpaperController::IsPolicyControlled(const AccountId& account_id, - bool is_persistent) const { + bool is_ephemeral) const { WallpaperInfo info; - if (!GetUserWallpaperInfo(account_id, &info, is_persistent)) + if (!GetUserWallpaperInfo(account_id, &info, is_ephemeral)) return false; return info.type == wallpaper::POLICY; } bool WallpaperController::CanSetUserWallpaper(const AccountId& account_id, - bool is_persistent) const { + bool is_ephemeral) const { // There is no visible wallpaper in kiosk mode. if (IsInKioskMode()) return false; // Don't allow user wallpapers while policy is in effect. - if (IsPolicyControlled(account_id, is_persistent)) { + if (IsPolicyControlled(account_id, is_ephemeral)) { return false; } return true; @@ -807,7 +807,7 @@ WallpaperInfo info; if (!GetUserWallpaperInfo(active_user_session->user_info->account_id, &info, - !active_user_session->user_info->is_ephemeral)) { + active_user_session->user_info->is_ephemeral)) { return std::string(); } return info.location; @@ -927,8 +927,8 @@ void WallpaperController::SetUserWallpaperInfo(const AccountId& account_id, const WallpaperInfo& info, - bool is_persistent) { - if (!is_persistent) { + bool is_ephemeral) { + if (is_ephemeral) { ephemeral_users_wallpaper_info_[account_id] = info; return; } @@ -938,7 +938,7 @@ if (!local_state) return; WallpaperInfo old_info; - if (GetUserWallpaperInfo(account_id, &old_info, is_persistent)) { + if (GetUserWallpaperInfo(account_id, &old_info, is_ephemeral)) { // Remove the color cache of the previous wallpaper if it exists. DictionaryPrefUpdate wallpaper_colors_update(local_state, prefs::kWallpaperColors); @@ -960,8 +960,8 @@ bool WallpaperController::GetUserWallpaperInfo(const AccountId& account_id, WallpaperInfo* info, - bool is_persistent) const { - if (!is_persistent) { + bool is_ephemeral) const { + if (is_ephemeral) { // Ephemeral users do not save anything to local state. Return true if the // info can be found in the map, otherwise return false. auto it = ephemeral_users_wallpaper_info_.find(account_id); @@ -1009,11 +1009,11 @@ void WallpaperController::InitializeUserWallpaperInfo( const AccountId& account_id, - bool is_persistent) { + bool is_ephemeral) { const wallpaper::WallpaperInfo info = { std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::DEFAULT, base::Time::Now().LocalMidnight()}; - SetUserWallpaperInfo(account_id, info, is_persistent); + SetUserWallpaperInfo(account_id, info, is_ephemeral); } void WallpaperController::SetArcWallpaper( @@ -1025,7 +1025,7 @@ wallpaper::WallpaperLayout layout, bool is_ephemeral, bool show_wallpaper) { - if (!CanSetUserWallpaper(account_id, !is_ephemeral)) + if (!CanSetUserWallpaper(account_id, is_ephemeral)) return; ash::mojom::WallpaperUserInfoPtr user_info = @@ -1095,7 +1095,7 @@ wallpaper::WallpaperLayout layout, const SkBitmap& image, bool show_wallpaper) { - if (!CanSetUserWallpaper(user_info->account_id, !user_info->is_ephemeral)) + if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)) return; SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name, wallpaper::CUSTOMIZED, layout, show_wallpaper, @@ -1110,7 +1110,7 @@ bool show_wallpaper) { DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted()); - if (!CanSetUserWallpaper(user_info->account_id, !user_info->is_ephemeral)) + if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)) return; gfx::ImageSkia online_wallpaper = gfx::ImageSkia::CreateFrom1xBitmap(image); @@ -1122,7 +1122,7 @@ WallpaperInfo info = {url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight()}; - SetUserWallpaperInfo(user_info->account_id, info, !user_info->is_ephemeral); + SetUserWallpaperInfo(user_info->account_id, info, user_info->is_ephemeral); if (show_wallpaper) SetWallpaperImage(online_wallpaper, info); @@ -1137,15 +1137,15 @@ mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, bool show_wallpaper) { - if (!CanSetUserWallpaper(user_info->account_id, !user_info->is_ephemeral)) + if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)) return; const AccountId account_id = user_info->account_id; - const bool is_persistent = !user_info->is_ephemeral; + const bool is_ephemeral = user_info->is_ephemeral; const user_manager::UserType type = user_info->type; RemoveUserWallpaper(std::move(user_info), wallpaper_files_id); - InitializeUserWallpaperInfo(account_id, is_persistent); + InitializeUserWallpaperInfo(account_id, is_ephemeral); if (show_wallpaper) { SetDefaultWallpaperImpl(account_id, type, true /*show_wallpaper=*/); } @@ -1223,7 +1223,7 @@ } WallpaperInfo info; if (!GetUserWallpaperInfo(user_info->account_id, &info, - !user_info->is_ephemeral) || + user_info->is_ephemeral) || info.type != wallpaper::CUSTOMIZED) { return; } @@ -1231,7 +1231,7 @@ return; info.layout = layout; - SetUserWallpaperInfo(user_info->account_id, info, !user_info->is_ephemeral); + SetUserWallpaperInfo(user_info->account_id, info, user_info->is_ephemeral); ShowUserWallpaper(std::move(user_info)); } @@ -1251,13 +1251,13 @@ } const AccountId account_id = current_user_->account_id; - const bool is_persistent = !current_user_->is_ephemeral; + const bool is_ephemeral = current_user_->is_ephemeral; // Guest user or regular user in ephemeral mode. // TODO(wzang/xdai): Check if the wallpaper info for ephemeral users should // be saved to local state. - if ((!is_persistent && current_user_->has_gaia_account) || + if ((is_ephemeral && current_user_->has_gaia_account) || current_user_->type == user_manager::USER_TYPE_GUEST) { - InitializeUserWallpaperInfo(account_id, is_persistent); + InitializeUserWallpaperInfo(account_id, is_ephemeral); SetDefaultWallpaperImpl(account_id, current_user_->type, true /*show_wallpaper=*/); LOG(ERROR) << "User is ephemeral or guest! Fallback to default wallpaper."; @@ -1265,9 +1265,9 @@ } WallpaperInfo info; - if (!GetUserWallpaperInfo(account_id, &info, is_persistent)) { - InitializeUserWallpaperInfo(account_id, is_persistent); - GetUserWallpaperInfo(account_id, &info, is_persistent); + if (!GetUserWallpaperInfo(account_id, &info, is_ephemeral)) { + InitializeUserWallpaperInfo(account_id, is_ephemeral); + GetUserWallpaperInfo(account_id, &info, is_ephemeral); } gfx::ImageSkia user_wallpaper; @@ -1339,20 +1339,20 @@ void WallpaperController::RemoveUserWallpaper( mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) { - RemoveUserWallpaperInfo(user_info->account_id, !user_info->is_ephemeral); + RemoveUserWallpaperInfo(user_info->account_id, user_info->is_ephemeral); RemoveUserWallpaperImpl(user_info->account_id, wallpaper_files_id); } void WallpaperController::RemovePolicyWallpaper( mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) { - DCHECK(IsPolicyControlled(user_info->account_id, !user_info->is_ephemeral)); + DCHECK(IsPolicyControlled(user_info->account_id, user_info->is_ephemeral)); // Updates the screen only when the user has logged in. const bool show_wallpaper = Shell::Get()->session_controller()->IsActiveUserSessionStarted(); // Removes the wallpaper info so that the user is no longer policy controlled, // otherwise setting default wallpaper is not allowed. - RemoveUserWallpaperInfo(user_info->account_id, !user_info->is_ephemeral); + RemoveUserWallpaperInfo(user_info->account_id, user_info->is_ephemeral); SetDefaultWallpaper(std::move(user_info), wallpaper_files_id, show_wallpaper); } @@ -1487,7 +1487,7 @@ } void WallpaperController::RemoveUserWallpaperInfo(const AccountId& account_id, - bool is_persistent) { + bool is_ephemeral) { if (wallpaper_cache_map_.find(account_id) != wallpaper_cache_map_.end()) wallpaper_cache_map_.erase(account_id); @@ -1496,7 +1496,7 @@ if (!local_state) return; WallpaperInfo info; - GetUserWallpaperInfo(account_id, &info, is_persistent); + GetUserWallpaperInfo(account_id, &info, is_ephemeral); DictionaryPrefUpdate prefs_wallpapers_info_update(local_state, prefs::kUserWallpaperInfo); prefs_wallpapers_info_update->RemoveWithoutPathExpansion( @@ -1674,7 +1674,7 @@ // appropriate wallpaper resolution. WallpaperInfo info = {relative_path, layout, type, base::Time::Now().LocalMidnight()}; - SetUserWallpaperInfo(user_info->account_id, info, !user_info->is_ephemeral); + SetUserWallpaperInfo(user_info->account_id, info, user_info->is_ephemeral); if (show_wallpaper) SetWallpaperImage(image, info); @@ -1846,7 +1846,7 @@ if (!active_user_session) return false; return IsPolicyControlled(active_user_session->user_info->account_id, - !active_user_session->user_info->is_ephemeral); + active_user_session->user_info->is_ephemeral); } bool WallpaperController::ShouldShowWallpaperSettingImpl() {
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index 2fe73e4e..663137a 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -250,13 +250,12 @@ // Returns whether a wallpaper policy is enforced for |account_id| (not // including device policy). - bool IsPolicyControlled(const AccountId& account_id, - bool is_persistent) const; + bool IsPolicyControlled(const AccountId& account_id, bool is_ephemeral) const; // When kiosk app is running or policy is enforced, setting a user wallpaper // is not allowed. bool CanSetUserWallpaper(const AccountId& account_id, - bool is_persistent) const; + bool is_ephemeral) const; // Prepares wallpaper to lock screen transition. Will apply blur if // |locking| is true and remove it otherwise. @@ -304,24 +303,22 @@ // Returns whether the current wallpaper is blurred. bool IsWallpaperBlurred() const { return is_wallpaper_blurred_; } - // TODO(crbug.com/776464): Change |is_persistent| to |is_ephemeral| to - // be consistent with |mojom::WallpaperUserInfo|. // Sets wallpaper info for |account_id| and saves it to local state if - // |is_persistent| is true. + // |is_ephemeral| is false. void SetUserWallpaperInfo(const AccountId& account_id, const wallpaper::WallpaperInfo& info, - bool is_persistent); + bool is_ephemeral); // Gets wallpaper info of |account_id| from local state, or memory if - // |is_persistent| is false. Returns false if wallpaper info is not found. + // |is_ephemeral| is true. Returns false if wallpaper info is not found. bool GetUserWallpaperInfo(const AccountId& account_id, wallpaper::WallpaperInfo* info, - bool is_persistent) const; + bool is_ephemeral) const; // Initializes wallpaper info for the user to default and saves it to local - // state if |is_persistent| is true. + // state if |is_ephemeral| is false. void InitializeUserWallpaperInfo(const AccountId& account_id, - bool is_persistent); + bool is_ephemeral); // TODO(crbug.com/776464): This method is a temporary workaround during the // refactoring. It should be combined with |SetCustomWallpaper|. @@ -348,7 +345,7 @@ // login screen right now. bool ShouldSetDevicePolicyWallpaper() const; - // mojom::WallpaperController overrides: + // mojom::WallpaperController: void Init(mojom::WallpaperControllerClientPtr client, const base::FilePath& user_data_path, const base::FilePath& chromeos_wallpapers_path, @@ -406,10 +403,10 @@ void ShowDefaultWallpaperForTesting(); // Creates an empty wallpaper. Some tests require a wallpaper widget is ready - // when running. However, the wallpaper widgets are now created - // asynchronously. If loading a real wallpaper, there are cases that these - // tests crash because the required widget is not ready. This function - // synchronously creates an empty widget for those tests to prevent crashes. + // when running. However, the wallpaper widgets are created asynchronously. If + // loading a real wallpaper, there are cases that these tests crash because + // the required widget is not ready. This function synchronously creates an + // empty widget for those tests to prevent crashes. void CreateEmptyWallpaperForTesting(); // Sets a test client interface with empty file paths. @@ -445,7 +442,7 @@ int GetWallpaperContainerId(bool locked); // Removes |account_id|'s wallpaper info and color cache if it exists. - void RemoveUserWallpaperInfo(const AccountId& account_id, bool is_persistent); + void RemoveUserWallpaperInfo(const AccountId& account_id, bool is_ephemeral); // Implementation of |RemoveUserWallpaper|, which deletes |account_id|'s // custom wallpapers and directories.
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index e78abed..5920f29b 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -390,7 +390,7 @@ relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight()}; controller_->SetUserWallpaperInfo(account_id, info, - true /*is_persistent=*/); + false /*is_ephemeral=*/); } // Simulates setting a custom wallpaper by directly setting the wallpaper @@ -401,7 +401,7 @@ wallpaper::WallpaperInfo("dummy_file_location", WALLPAPER_LAYOUT_CENTER, wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight()), - true /*is_persistent=*/); + false /*is_ephemeral=*/); } // Initializes default wallpaper paths "*default_*file" and writes JPEG @@ -841,7 +841,7 @@ EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::CUSTOMIZED); wallpaper::WallpaperInfo wallpaper_info; EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo expected_wallpaper_info( base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout, wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight()); @@ -855,7 +855,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, expected_wallpaper_info); } @@ -874,7 +874,7 @@ EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::ONLINE); wallpaper::WallpaperInfo wallpaper_info; EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo expected_wallpaper_info( url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight()); EXPECT_EQ(wallpaper_info, expected_wallpaper_info); @@ -886,7 +886,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, expected_wallpaper_info); } @@ -898,9 +898,9 @@ // The user starts with no wallpaper info and is not controlled by policy. wallpaper::WallpaperInfo wallpaper_info; EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); EXPECT_FALSE( - controller_->IsPolicyControlled(account_id_1, true /*is_persistent=*/)); + controller_->IsPolicyControlled(account_id_1, false /*is_ephemeral=*/)); // A default wallpaper is shown for the user. controller_->ShowUserWallpaper(InitializeUser(account_id_1)); EXPECT_EQ(1, GetWallpaperCount()); @@ -913,7 +913,7 @@ std::string() /*data=*/); RunAllTasksUntilIdle(); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo policy_wallpaper_info( base::FilePath(wallpaper_files_id_1) .Append("policy-controlled.jpeg") @@ -922,7 +922,7 @@ base::Time::Now().LocalMidnight()); EXPECT_EQ(wallpaper_info, policy_wallpaper_info); EXPECT_TRUE( - controller_->IsPolicyControlled(account_id_1, true /*is_persistent=*/)); + controller_->IsPolicyControlled(account_id_1, false /*is_ephemeral=*/)); // Verify the wallpaper is not updated since the user hasn't logged in. EXPECT_EQ(0, GetWallpaperCount()); @@ -939,13 +939,13 @@ wallpaper_files_id_1); WaitUntilCustomWallpapersDeleted(account_id_1); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo default_wallpaper_info( std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::DEFAULT, base::Time::Now().LocalMidnight()); EXPECT_EQ(wallpaper_info, default_wallpaper_info); EXPECT_FALSE( - controller_->IsPolicyControlled(account_id_1, true /*is_persistent=*/)); + controller_->IsPolicyControlled(account_id_1, false /*is_ephemeral=*/)); // Verify the wallpaper is not updated since the user hasn't logged in. EXPECT_EQ(0, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::POLICY); @@ -965,7 +965,7 @@ SimulateSettingCustomWallpaper(account_id_1); wallpaper::WallpaperInfo wallpaper_info; EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo default_wallpaper_info( std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::DEFAULT, base::Time::Now().LocalMidnight()); @@ -986,7 +986,7 @@ {wallpaper_dir_->GetPath().Append(default_large_wallpaper_name)})); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); // The user wallpaper info has been reset to the default value. EXPECT_EQ(wallpaper_info, default_wallpaper_info); @@ -1006,7 +1006,7 @@ {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)})); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); // The user wallpaper info has been reset to the default value. EXPECT_EQ(wallpaper_info, default_wallpaper_info); @@ -1026,7 +1026,7 @@ {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)})); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); // The user wallpaper info has been reset to the default value. EXPECT_EQ(wallpaper_info, default_wallpaper_info); } @@ -1079,7 +1079,7 @@ SimulateSettingCustomWallpaper(account_id_1); wallpaper::WallpaperInfo wallpaper_info; EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo default_wallpaper_info( std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::DEFAULT, base::Time::Now().LocalMidnight()); @@ -1099,7 +1099,7 @@ EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, default_wallpaper_info); EXPECT_TRUE(CompareDecodeFilePaths( {wallpaper_dir_->GetPath().Append(guest_large_wallpaper_name)})); @@ -1135,7 +1135,7 @@ EXPECT_EQ(0, GetWallpaperCount()); wallpaper::WallpaperInfo wallpaper_info; EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); // Verify that |SetOnlineWallpaper| doesn't set wallpaper in kiosk mode, and // |account_id|'s wallpaper info is not updated. @@ -1145,7 +1145,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); // Verify that |SetDefaultWallpaper| doesn't set wallpaper in kiosk mode, and // |account_id|'s wallpaper info is not updated. @@ -1155,7 +1155,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); } TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) { @@ -1168,9 +1168,9 @@ "dummy_file_location", WALLPAPER_LAYOUT_CENTER, wallpaper::POLICY, base::Time::Now().LocalMidnight()); controller_->SetUserWallpaperInfo(account_id_1, policy_wallpaper_info, - true /*is_persistent=*/); + false /*is_ephemeral=*/); EXPECT_TRUE( - controller_->IsPolicyControlled(account_id_1, true /*is_persistent=*/)); + controller_->IsPolicyControlled(account_id_1, false /*is_ephemeral=*/)); // Verify that |SetCustomWallpaper| doesn't set wallpaper when policy is // enforced, and |account_id|'s wallpaper info is not updated. @@ -1181,7 +1181,7 @@ EXPECT_EQ(0, GetWallpaperCount()); wallpaper::WallpaperInfo wallpaper_info; EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, policy_wallpaper_info); // Verify that |SetOnlineWallpaper| doesn't set wallpaper when policy is @@ -1192,7 +1192,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, policy_wallpaper_info); // Verify that |SetDefaultWallpaper| doesn't set wallpaper when policy is @@ -1203,7 +1203,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, policy_wallpaper_info); } @@ -1377,7 +1377,7 @@ EXPECT_EQ(controller_->GetWallpaperLayout(), layout); wallpaper::WallpaperInfo wallpaper_info; EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); wallpaper::WallpaperInfo expected_wallpaper_info( base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout, wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight()); @@ -1392,7 +1392,7 @@ EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperLayout(), layout); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); expected_wallpaper_info.layout = layout; EXPECT_EQ(wallpaper_info, expected_wallpaper_info); @@ -1406,7 +1406,7 @@ EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::ONLINE); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /*is_persistent=*/)); + false /*is_ephemeral=*/)); expected_wallpaper_info.type = wallpaper::ONLINE; expected_wallpaper_info.location = url; EXPECT_EQ(wallpaper_info, expected_wallpaper_info); @@ -1420,7 +1420,7 @@ EXPECT_EQ(controller_->GetWallpaperLayout(), layout); // The saved wallpaper info is not updated. EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, - true /* is_persistent */)); + false /*is_ephemeral=*/)); EXPECT_EQ(wallpaper_info, expected_wallpaper_info); }
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc index 5c1174c..bd20d5a5 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -122,7 +122,7 @@ TabletModeController::TabletModeController() : tablet_mode_usage_interval_start_time_(base::Time::Now()), - tick_clock_(std::make_unique<base::DefaultTickClock>()), + tick_clock_(base::DefaultTickClock::GetInstance()), auto_hide_title_bars_(!base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshDisableTabletAutohideTitlebars)), binding_(this), @@ -532,10 +532,9 @@ return elapsed_time >= kUnstableLidAngleDuration; } -void TabletModeController::SetTickClockForTest( - std::unique_ptr<base::TickClock> tick_clock) { +void TabletModeController::SetTickClockForTest(base::TickClock* tick_clock) { DCHECK(tick_clock_); - tick_clock_ = std::move(tick_clock); + tick_clock_ = tick_clock; } } // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h index 97ce7afe9..ba802f6e 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.h +++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -154,7 +154,9 @@ // Set the TickClock. This is only to be used by tests that need to // artificially and deterministically control the current time. - void SetTickClockForTest(std::unique_ptr<base::TickClock> tick_clock); + // This does not take the ownership of the tick_clock. |tick_clock| must + // outlive the TabletModeController instance. + void SetTickClockForTest(base::TickClock* tick_clock); // Detect hinge rotation from base and lid accelerometers and automatically // start / stop tablet mode. @@ -229,7 +231,7 @@ base::TimeTicks first_unstable_lid_angle_time_; // Source for the current time in base::TimeTicks. - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; // Set when tablet mode switch is on. This is used to force tablet mode. bool tablet_mode_switch_is_on_ = false;
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc index f642995..8372c18 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -121,15 +121,12 @@ // Attaches a SimpleTestTickClock to the TabletModeController with a non // null value initial value. void AttachTickClockForTest() { - std::unique_ptr<base::TickClock> tick_clock( - test_tick_clock_ = new base::SimpleTestTickClock()); - test_tick_clock_->Advance(base::TimeDelta::FromSeconds(1)); - tablet_mode_controller()->SetTickClockForTest(std::move(tick_clock)); + test_tick_clock_.Advance(base::TimeDelta::FromSeconds(1)); + tablet_mode_controller()->SetTickClockForTest(&test_tick_clock_); } void AdvanceTickClock(const base::TimeDelta& delta) { - DCHECK(test_tick_clock_); - test_tick_clock_->Advance(delta); + test_tick_clock_.Advance(delta); } void OpenLidToAngle(float degrees) { @@ -183,7 +180,7 @@ base::UserActionTester* user_action_tester() { return &user_action_tester_; } private: - base::SimpleTestTickClock* test_tick_clock_; + base::SimpleTestTickClock test_tick_clock_; // Tracks user action counts. base::UserActionTester user_action_tester_;
diff --git a/base/android/java/src/org/chromium/base/CollectionUtil.java b/base/android/java/src/org/chromium/base/CollectionUtil.java index 0a9a5c7..38d96f5 100644 --- a/base/android/java/src/org/chromium/base/CollectionUtil.java +++ b/base/android/java/src/org/chromium/base/CollectionUtil.java
@@ -4,6 +4,7 @@ package org.chromium.base; +import android.support.annotation.NonNull; import android.util.Pair; import java.util.ArrayList; @@ -11,6 +12,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -55,6 +57,22 @@ return map; } + public static int[] integerListToIntArray(@NonNull List<Integer> list) { + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } + + public static long[] longListToLongArray(@NonNull List<Long> list) { + long[] array = new long[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } + // This is a utility helper method that adds functionality available in API 24 (see // Collection.forEach). public static <T> void forEach(Collection<? extends T> collection, Callback<T> worker) {
diff --git a/base/observer_list.h b/base/observer_list.h index adf3e67..e900e435 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -89,9 +89,15 @@ }; // When check_empty is true, assert that the list is empty on destruction. -template <class ObserverType, bool check_empty = false> +// When allow_reentrancy is false, iterating throught the list while already in +// the iteration loop will result in DCHECK failure. +// TODO(oshima): Change the default to non reentrant. https://crbug.com/812109 +template <class ObserverType, + bool check_empty = false, + bool allow_reentrancy = true> class ObserverList - : public SupportsWeakPtr<ObserverList<ObserverType, check_empty>> { + : public SupportsWeakPtr< + ObserverList<ObserverType, check_empty, allow_reentrancy>> { public: // An iterator class that can be used to access the list of observers. class Iter { @@ -111,6 +117,7 @@ ? std::numeric_limits<size_t>::max() : list->observers_.size()) { DCHECK(list_); + DCHECK(allow_reentrancy || !list_->live_iterator_count_); EnsureValidIndex(); ++list_->live_iterator_count_; } @@ -292,6 +299,9 @@ DISALLOW_COPY_AND_ASSIGN(ObserverList); }; +template <class ObserverType, bool check_empty = false> +using ReentrantObserverList = ObserverList<ObserverType, check_empty, true>; + } // namespace base #endif // BASE_OBSERVER_LIST_H_
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc index 9cbb168..8575bc7 100644 --- a/base/observer_list_unittest.cc +++ b/base/observer_list_unittest.cc
@@ -23,6 +23,7 @@ #include "base/test/scoped_task_environment.h" #include "base/threading/platform_thread.h" #include "base/threading/thread_restrictions.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -1227,4 +1228,52 @@ EXPECT_EQ(-10, b.total); } +class MockLogAssertHandler { + public: + MOCK_METHOD4( + HandleLogAssert, + void(const char*, int, const base::StringPiece, const base::StringPiece)); +}; + +#if DCHECK_IS_ON() +TEST(ObserverListTest, NonReentrantObserverList) { + using ::testing::_; + + ObserverList<Foo, /*check_empty=*/false, /*allow_reentrancy=*/false> + non_reentrant_observer_list; + Adder a(1); + non_reentrant_observer_list.AddObserver(&a); + + ::testing::StrictMock<MockLogAssertHandler> handler; + EXPECT_CALL(handler, HandleLogAssert(_, _, _, _)).Times(1); + { + logging::ScopedLogAssertHandler scoped_handler_b(base::BindRepeating( + &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler))); + for (const Foo& a : non_reentrant_observer_list) { + for (const Foo& b : non_reentrant_observer_list) { + std::ignore = a; + std::ignore = b; + } + } + } +} + +TEST(ObserverListTest, ReentrantObserverList) { + using ::testing::_; + + ReentrantObserverList<Foo> reentrant_observer_list; + Adder a(1); + reentrant_observer_list.AddObserver(&a); + bool passed = false; + for (const Foo& a : reentrant_observer_list) { + for (const Foo& b : reentrant_observer_list) { + std::ignore = a; + std::ignore = b; + passed = true; + } + } + EXPECT_TRUE(passed); +} +#endif + } // namespace base
diff --git a/build/fuchsia/runner_v2/common_args.py b/build/fuchsia/runner_v2/common_args.py index f879520..367491f 100644 --- a/build/fuchsia/runner_v2/common_args.py +++ b/build/fuchsia/runner_v2/common_args.py
@@ -4,6 +4,7 @@ import logging import os +import sys from device_target import DeviceTarget from qemu_target import QemuTarget @@ -33,24 +34,35 @@ common_args.add_argument('--port', '-p', type=int, default=22, help='The port of the SSH service running on the ' + 'device. Optional.') - common_args.add_argument('--ssh_config', '-F', + common_args.add_argument('--ssh-config', '-F', help='The path to the SSH configuration used for ' 'connecting to the target device.') common_args.add_argument('--verbose', '-v', default=False, action='store_true', help='Show more logging information.') + common_args.add_argument('--really-verbose', '-vv', default=False, + action='store_true', + help='Show even more logging information, ' + + 'including SCP logs.') def ConfigureLogging(args): """Configures the logging level based on command line |args|.""" - logging.basicConfig(level=(logging.DEBUG if args.verbose else logging.INFO)) + if args.really_verbose: + args.verbose = True + + logging.basicConfig(level=(logging.DEBUG if args.verbose else logging.INFO), + format='%(asctime)s:%(levelname)s:%(name)s:%(message)s') # The test server spawner is too noisy with INFO level logging, so tweak # its verbosity a bit by adjusting its logging level. - if args.verbose: - logging.getLogger('chrome_test_server_spawner').setLevel(logging.DEBUG) - else: - logging.getLogger('chrome_test_server_spawner').setLevel(logging.WARN) + logging.getLogger('chrome_test_server_spawner').setLevel( + logging.DEBUG if args.verbose else logging.WARN) + + # Verbose SCP output can be useful at times but oftentimes is just too noisy. + # Only enable it if -vv is passed. + logging.getLogger('ssh').setLevel( + logging.DEBUG if args.really_verbose else logging.WARN) def GetDeploymentTargetForArgs(args):
diff --git a/build/fuchsia/runner_v2/device_target.py b/build/fuchsia/runner_v2/device_target.py index 25b1116..8e8fc678 100644 --- a/build/fuchsia/runner_v2/device_target.py +++ b/build/fuchsia/runner_v2/device_target.py
@@ -31,6 +31,7 @@ self._port = 22 self._auto = not host or not ssh_config + self._new_instance = True if self._auto: self._ssh_config_path = boot_data.GetSSHConfigPath(output_dir) @@ -62,6 +63,7 @@ self._host = self.__Discover(node_name) if self._host and self._WaitUntilReady(retries=0): logging.info('Connected to an already booted device.') + self._new_instance = False return logging.info('Netbooting Fuchsia. ' + @@ -100,6 +102,9 @@ self._WaitUntilReady(); + def IsNewInstance(self): + return self._new_instance + def _GetEndpoint(self): return (self._host, self._port)
diff --git a/build/fuchsia/runner_v2/qemu_target.py b/build/fuchsia/runner_v2/qemu_target.py index 1a12f687..0c1a14d 100644 --- a/build/fuchsia/runner_v2/qemu_target.py +++ b/build/fuchsia/runner_v2/qemu_target.py
@@ -65,12 +65,13 @@ 'bootdata-blobstore.bin'), '-smp', '4', - # Attach the blobstore and data volumes. - '-drive', 'file=%s,format=qcow2,if=none,id=data' % - self._MakeQcowDisk( - boot_data.GetTargetFile(self._GetTargetSdkArch(), - 'fvm.blk')), - '-drive', 'file=%s,format=qcow2,if=none,id=blobstore' % + # Attach the blobstore and data volumes. Use snapshot mode to discard + # any changes. + '-snapshot', + '-drive', 'file=%s,format=qcow2,if=none,id=data,snapshot=on' % + boot_data.GetTargetFile(self._GetTargetSdkArch(), + 'fvm.blk.qcow2'), + '-drive', 'file=%s,format=qcow2,if=none,id=blobstore,snapshot=on' % self._MakeQcowDisk(boot_data.ConfigureDataFVM(self._output_dir, False)), '-device', 'virtio-blk-pci,drive=data',
diff --git a/build/fuchsia/runner_v2/remote_cmd.py b/build/fuchsia/runner_v2/remote_cmd.py index ab07047..67d107f9 100644 --- a/build/fuchsia/runner_v2/remote_cmd.py +++ b/build/fuchsia/runner_v2/remote_cmd.py
@@ -12,6 +12,7 @@ _SSH = ['ssh'] _SCP = ['scp', '-C'] # Use gzip compression. +_SSH_LOGGER = logging.getLogger('ssh') COPY_TO_TARGET = 0 COPY_FROM_TARGET = 1 @@ -35,7 +36,7 @@ ssh_command = _SSH + ['-F', config_path, host, '-p', str(port)] + command - logging.debug('ssh exec: ' + ' '.join(ssh_command)) + _SSH_LOGGER.debug('ssh exec: ' + ' '.join(ssh_command)) if silent: devnull = open(os.devnull, 'w') return subprocess.call(ssh_command, stderr=devnull, stdout=devnull) @@ -66,11 +67,11 @@ ssh_command = _SSH + ['-F', config_path, host, '-p', str(port)] + ssh_args + ['--'] + command - logging.debug(' '.join(ssh_command)) + _SSH_LOGGER.debug(' '.join(ssh_command)) return subprocess.Popen(ssh_command, **kwargs) -def RunScp(config_path, host, port, sources, dest, direction): +def RunScp(config_path, host, port, sources, dest, direction, recursive=False): """Copies a file to or from a remote host using SCP and blocks until completion. @@ -82,6 +83,7 @@ direction: Indicates whether the file should be copied to or from the remote side. Valid values are COPY_TO_TARGET or COPY_FROM_TARGET. + recursive: If true, performs a recursive copy. Function will raise an assertion if a failure occurred.""" @@ -89,8 +91,10 @@ if ':' in host: scp_command.append('-6') host = '[' + host + ']' - if logging.getLogger().getEffectiveLevel() == logging.DEBUG: + if _SSH_LOGGER.getEffectiveLevel() == logging.DEBUG: scp_command.append('-v') + if recursive: + scp_command.append('-r') if direction == COPY_TO_TARGET: dest = "%s:%s" % (host, dest) @@ -101,5 +105,5 @@ scp_command += sources scp_command += [dest] - logging.debug(' '.join(scp_command)) + _SSH_LOGGER.debug(' '.join(scp_command)) subprocess.check_call(scp_command, stdout=open(os.devnull, 'w'))
diff --git a/build/fuchsia/runner_v2/run_package.py b/build/fuchsia/runner_v2/run_package.py index e8e79a1..d7b57fe 100644 --- a/build/fuchsia/runner_v2/run_package.py +++ b/build/fuchsia/runner_v2/run_package.py
@@ -5,14 +5,141 @@ """Contains a helper function for deploying and executing a packaged executable on a Target.""" +import common +import json import logging import os +import shutil import subprocess +import tempfile import uuid from symbolizer import FilterStream -def RunPackage(output_dir, target, package_path, run_args, symbolizer_config=None): +FAR = os.path.join(common.SDK_ROOT, 'tools', 'far') +PM = os.path.join(common.SDK_ROOT, 'tools', 'pm') + + +def _Deploy(target, output_dir, archive_path): + """Converts the FAR archive at |archive_path| into a Fuchsia package + and deploys it to |target|'s blobstore. If |incremental| is set, + then the remote target's blobstore is queried and only the changed blobs + are copied. + + Returns: the name of the package, which can be run by executing + 'run <package_name>' on the target.""" + + logging.info('Deploying package to target.') + + staging_path = None + blob_link_dir = None + far_contents_dir = None + try: + package_name = os.path.basename(archive_path) + + logging.debug('Extracting archive contents.') + far_contents_dir = tempfile.mkdtemp() + subprocess.check_call([FAR, 'extract', '--archive=%s' % archive_path, + '--output=%s' % far_contents_dir]) + + logging.debug('Building package metadata.') + with open(os.path.join(far_contents_dir, 'meta', 'package.json'), 'w') \ + as package_json: + json.dump({'version': '0', 'name': package_name}, package_json) + manifest = tempfile.NamedTemporaryFile() + for root, _, files in os.walk(far_contents_dir): + for f in files: + path = os.path.join(root, f) + manifest.write('%s=%s\n' % + (os.path.relpath(path, far_contents_dir), path)) + manifest.flush() + + # Generate the package signing key. + signing_key_path = os.path.join(output_dir, 'signing-key') + if not os.path.exists(signing_key_path): + subprocess.check_call([PM, '-k', signing_key_path, 'genkey']) + + # Build the package metadata archive. + staging_path = tempfile.mkdtemp() + subprocess.check_call([PM, '-o', staging_path, '-k', signing_key_path, + '-m', manifest.name, 'build']) + + # If the target is already warm, then it's possible that some time can be + # saved by only sending the sending the changed blobs. + # If the target is newly booted, however, it can be safely assumed that the + # target doesn't contain the blobs, so the query step can be skipped. + existing_blobs = set() + if not target.IsNewInstance(): + logging.debug('Querying the target blobstore\'s state.') + ls = target.RunCommandPiped(['ls', '/blobstore'], stdout=subprocess.PIPE) + for blob in ls.stdout: + existing_blobs.add(blob.strip()) + ls.wait() + + # Locally stage the blobs and metadata into a local temp dir to prepare for + # a one-shot 'scp' copy. + blob_link_dir = tempfile.mkdtemp() + os.symlink(os.path.join(staging_path, 'meta.far'), + os.path.join(blob_link_dir, 'meta.far')) + for next_line in open(os.path.join(staging_path, 'meta', 'contents')): + rel_path, blob = next_line.strip().split('=') + dest_path = os.path.join(blob_link_dir, blob) + if blob not in existing_blobs: + existing_blobs.add(blob) + os.symlink(os.path.join(far_contents_dir, rel_path), + os.path.join(blob_link_dir, blob)) + + # Copy the package metadata and contents into tmpfs, and then execute + # remote commands to copy the data into pkgfs/incoming. + # We can't use 'scp' to copy directly into /pkgfs/incoming due to a bug in + # Fuchsia (see bug PKG-9). + logging.debug('Deploying to target blobstore.') + target.PutFile(blob_link_dir, '/tmp', recursive=True) + + # Copy everything into target's /pkgfs/incoming and then clean up. + # The command is joined with double ampersands so that all the steps can + # be done over the lifetime of a single SSH connection. + # Note that 'mv' moves to pkgfs are unsupported (Fuchsia bug PKG-9). + blob_tmpdir = os.path.join('/tmp/', os.path.basename(blob_link_dir)) + result = target.RunCommand([ + # Speed things up by using builtin commands, which don't suffer the + # dynamic library loading speed penalty that's present in the + # executables. + 'unset PATH', '&&' + + # Separate meta.far from the blobs so we can add the blobs in + # bulk in advance of registering the package (faster). + 'mv', os.path.join(blob_tmpdir, 'meta.far'), '/tmp', '&&', + + # Register the package. + 'cp', '/tmp/meta.far', '/pkgfs/incoming', '&&', + + # Install the blobs into /pkgfs. + 'for', 'f', 'in', os.path.join(blob_tmpdir, '*'), ';', 'do', + 'cp', '$f', '/pkgfs/incoming', ';', + 'done', '&&', + + 'rm', '-rf', blob_tmpdir, '&&', + + 'rm', '/tmp/meta.far']) + + + if result != 0: + raise Exception('Deployment failed.') + + return package_name + + finally: + if blob_link_dir: + shutil.rmtree(blob_link_dir) + if staging_path: + shutil.rmtree(staging_path) + if far_contents_dir: + shutil.rmtree(far_contents_dir) + + +def RunPackage(output_dir, target, package_path, run_args, + symbolizer_config=None): """Copies the Fuchsia package at |package_path| to the target, executes it with |run_args|, and symbolizes its output. @@ -25,44 +152,29 @@ Returns the exit code of the remote package process.""" + + package_name = _Deploy(target, output_dir, package_path) + command = ['run', package_name] + run_args + process = target.RunCommandPiped(command, + stdin=open(os.devnull, 'r'), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + if symbolizer_config: - if logging.getLogger().getEffectiveLevel() == logging.DEBUG: - logging.debug('Contents of package "%s":' % os.path.basename(package_path)) - for next_line in open(symbolizer_config, 'r'): - logging.debug(' ' + next_line.strip().split('=')[0]) - logging.debug('') + # Decorate the process output stream with the symbolizer. + output = FilterStream(process.stdout, package_name, + symbolizer_config, output_dir) + else: + output = process.stdout - # Deploy the package file to a unique path on the target. - # The package's UUID length is truncated so as to not overrun the filename - # field in the backtrace output. - unique_package_name = 'package-%s.far' % str(uuid.uuid4())[:18] - deployed_package_path = '/tmp/' + unique_package_name - target.PutFile(package_path, deployed_package_path) + for next_line in output: + print next_line - try: - command = ['run', deployed_package_path] + run_args - process = target.RunCommandPiped(command, - stdin=open(os.devnull, 'r'), - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - if symbolizer_config: - # Decorate the process output stream with the symbolizer. - output = FilterStream(process.stdout, unique_package_name, - symbolizer_config, output_dir) - else: - output = process.stdout - - for next_line in output: - print next_line - - process.wait() - if process.returncode != 0: - # The test runner returns an error status code if *any* tests fail, - # so we should proceed anyway. - logging.warning('Command exited with non-zero status code %d.' % - process.returncode) - finally: - logging.debug('Cleaning up package file.') - target.RunCommand(['rm', deployed_package_path]) + process.wait() + if process.returncode != 0: + # The test runner returns an error status code if *any* tests fail, + # so we should proceed anyway. + logging.warning('Command exited with non-zero status code %d.' % + process.returncode) return process.returncode
diff --git a/build/fuchsia/runner_v2/target.py b/build/fuchsia/runner_v2/target.py index 31f98b4..b5a8bfa 100644 --- a/build/fuchsia/runner_v2/target.py +++ b/build/fuchsia/runner_v2/target.py
@@ -38,13 +38,20 @@ def Start(self): """Handles the instantiation and connection process for the Fuchsia target instance.""" + pass def IsStarted(self): - """Returns true if the Fuchsia target instance is ready to accept + """Returns True if the Fuchsia target instance is ready to accept commands.""" + return self._started + def IsNewInstance(self): + """Returns True if the connected target instance is newly provisioned.""" + + return True + def RunCommandPiped(self, command, **kwargs): """Starts a remote command and immediately returns a Popen object for the command. The caller may interact with the streams, inspect the status code, @@ -75,27 +82,30 @@ return remote_cmd.RunSsh(self._GetSshConfigPath(), host, port, command, silent) - def PutFile(self, source, dest): + def PutFile(self, source, dest, recursive=False): """Copies a file from the local filesystem to the target filesystem. source: The path of the file being copied. - dest: The path on the remote filesystem which will be copied to.""" + dest: The path on the remote filesystem which will be copied to. + recursive: If true, performs a recursive copy.""" assert type(source) is str - self.PutFiles([source], dest) + self.PutFiles([source], dest, recursive) - def PutFiles(self, sources, dest): + def PutFiles(self, sources, dest, recursive=False): """Copies files from the local filesystem to the target filesystem. sources: List of local file paths to copy from, or a single path. - dest: The path on the remote filesystem which will be copied to.""" + dest: The path on the remote filesystem which will be copied to. + recursive: If true, performs a recursive copy.""" assert type(sources) is tuple or type(sources) is list self._AssertIsStarted() host, port = self._GetEndpoint() logging.debug('copy local:%s => remote:%s' % (sources, dest)) command = remote_cmd.RunScp(self._GetSshConfigPath(), host, port, - sources, dest, remote_cmd.COPY_TO_TARGET) + sources, dest, remote_cmd.COPY_TO_TARGET, + recursive) def GetFile(self, source, dest): """Copies a file from the target filesystem to the local filesystem.
diff --git a/build/fuchsia/update_sdk.py b/build/fuchsia/update_sdk.py index 882a64c6..da161989 100755 --- a/build/fuchsia/update_sdk.py +++ b/build/fuchsia/update_sdk.py
@@ -13,7 +13,7 @@ import tarfile import tempfile -SDK_HASH = '739d1fd10565f97bacae8215903403b2677d8f48' +SDK_HASH = 'af9c3aa2c72798dbb58a70de610bb7a30df322c0' REPOSITORY_ROOT = os.path.abspath(os.path.join( os.path.dirname(__file__), '..', '..'))
diff --git a/build/toolchain/concurrent_links.gni b/build/toolchain/concurrent_links.gni index 1a7b727..e68384f3 100644 --- a/build/toolchain/concurrent_links.gni +++ b/build/toolchain/concurrent_links.gni
@@ -38,12 +38,13 @@ } else if (is_android && !is_component_build && symbol_level == 2) { # Full debug symbols require large memory for link. _args = [ "--mem_per_link_gb=25" ] - } else if (is_android && !is_debug && !using_sanitizer && symbol_level == 1) { + } else if (is_android && !is_debug && !using_sanitizer && symbol_level == 0) { # Increase the number of concurrent links for release bots. Debug builds # make heavier use of ProGuard, and so should not be raised. Sanitizers also # increase the memory overhead. _args = [ "--mem_per_link_gb=4" ] - } else if (is_linux && !is_chromeos && symbol_level == 1) { + } else if (is_linux && !is_chromeos && symbol_level == 0) { + # Memory consumption on link without debug symbols is low on linux. _args = [ "--mem_per_link_gb=3" ] } else { _args = []
diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc index 101cf15d..60c64503 100644 --- a/cc/test/skia_common.cc +++ b/cc/test/skia_common.cc
@@ -107,6 +107,7 @@ PaintImage CreateBitmapImage(const gfx::Size& size) { SkBitmap bitmap; bitmap.allocN32Pixels(size.width(), size.height()); + bitmap.eraseColor(SK_AlphaTRANSPARENT); return PaintImageBuilder::WithDefault() .set_id(PaintImage::GetNextId()) .set_image(SkImage::MakeFromBitmap(bitmap),
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index fda7a4dfc..97b242c 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -1514,10 +1514,17 @@ } size_t data_size = image_info.computeMinByteSize(); - return base::WrapRefCounted( - new ImageData(mode, data_size, draw_image.target_color_space(), - CalculateDesiredFilterQuality(draw_image), mip_level, - !draw_image.paint_image().IsLazyGenerated())); + // |is_bitmap_backed| specifies whether the image has pixel data which can + // directly be used for the upload. This will be the case for non-lazy images + // used at the original scale. In these cases, we don't internally cache any + // cpu component for the image. + // However, if the image will be scaled, we consider it a lazy image and cache + // the scaled result in discardable memory. + const bool is_bitmap_backed = + !draw_image.paint_image().IsLazyGenerated() && mip_level == 0; + return base::WrapRefCounted(new ImageData( + mode, data_size, draw_image.target_color_space(), + CalculateDesiredFilterQuality(draw_image), mip_level, is_bitmap_backed)); } void GpuImageDecodeCache::DeleteImage(ImageData* image_data) {
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc index d0046c72..52395c49 100644 --- a/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -2210,7 +2210,7 @@ cache->UnrefImage(draw_image); } -TEST_P(GpuImageDecodeCacheTest, NonLazyImageUpload) { +TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadNoScale) { auto cache = CreateCache(); bool is_decomposable = true; SkFilterQuality quality = kHigh_SkFilterQuality; @@ -2226,6 +2226,33 @@ EXPECT_TRUE(decoded_draw_image.image()); EXPECT_TRUE(decoded_draw_image.is_budgeted()); cache->DrawWithImageFinished(draw_image, decoded_draw_image); + // For non-lazy images used at the original scale, no cpu component should be + // cached + EXPECT_FALSE(cache->GetSWImageDecodeForTesting(draw_image)); +} + +TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadDownscaled) { + auto cache = CreateCache(); + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage image = CreateBitmapImage(gfx::Size(10, 10)); + DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()), + quality, + CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable), + PaintImage::kDefaultFrameIndex, DefaultColorSpace()); + viz::ContextProvider::ScopedContextLock context_lock(context_provider()); + DecodedDrawImage decoded_draw_image = + EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image)); + EXPECT_TRUE(decoded_draw_image.image()); + EXPECT_TRUE(decoded_draw_image.is_budgeted()); + cache->DrawWithImageFinished(draw_image, decoded_draw_image); + // For non-lazy images which are downscaled, the scaled image should be + // cached. + auto sw_image = cache->GetSWImageDecodeForTesting(draw_image); + EXPECT_TRUE(sw_image); + EXPECT_EQ(sw_image->width(), 5); + EXPECT_EQ(sw_image->height(), 5); } INSTANTIATE_TEST_CASE_P(
diff --git a/chrome/VERSION b/chrome/VERSION index 6d128fd..ab899ee 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=66 MINOR=0 -BUILD=3357 +BUILD=3358 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 5cc944ce..b35cb18c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -240,6 +240,7 @@ "OmniboxVoiceSearchAlwaysVisible"; public static final String PAY_WITH_GOOGLE_V1 = "PayWithGoogleV1"; public static final String PASSWORD_SEARCH = "PasswordSearchMobile"; + public static final String PERMISSION_DELEGATION = "PermissionDelegation"; public static final String PROGRESS_BAR_THROTTLE = "ProgressBarThrottle"; public static final String PWA_PERSISTENT_NOTIFICATION = "PwaPersistentNotification"; public static final String READER_MODE_IN_CCT = "ReaderModeInCCT";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java index 534798d..ebdf1d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -26,11 +26,11 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Build; -import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Base64; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.CollectionUtil; import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.ThreadUtils; @@ -744,27 +744,14 @@ } nativeOnWebApksRetrieved(callbackPointer, names.toArray(new String[0]), shortNames.toArray(new String[0]), packageNames.toArray(new String[0]), - integerListToIntArray(shellApkVersions), integerListToIntArray(versionCodes), - uris.toArray(new String[0]), scopes.toArray(new String[0]), - manifestUrls.toArray(new String[0]), manifestStartUrls.toArray(new String[0]), - integerListToIntArray(displayModes), integerListToIntArray(orientations), - longListToLongArray(themeColors), longListToLongArray(backgroundColors)); - } - - private static int[] integerListToIntArray(@NonNull List<Integer> list) { - int[] array = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); - } - return array; - } - - private static long[] longListToLongArray(@NonNull List<Long> list) { - long[] array = new long[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); - } - return array; + CollectionUtil.integerListToIntArray(shellApkVersions), + CollectionUtil.integerListToIntArray(versionCodes), uris.toArray(new String[0]), + scopes.toArray(new String[0]), manifestUrls.toArray(new String[0]), + manifestStartUrls.toArray(new String[0]), + CollectionUtil.integerListToIntArray(displayModes), + CollectionUtil.integerListToIntArray(orientations), + CollectionUtil.longListToLongArray(themeColors), + CollectionUtil.longListToLongArray(backgroundColors)); } private static native void nativeOnWebappDataStored(long callbackPointer);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 1cd51ee8..4213c9b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -83,7 +83,7 @@ import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.chrome.browser.util.UrlUtilities; -import org.chromium.chrome.browser.webapps.WebappInterceptNavigationDelegate; +import org.chromium.chrome.browser.webapps.WebappCustomTabTimeSpentLogger; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationEntry; @@ -148,7 +148,7 @@ private final CustomTabsConnection mConnection = CustomTabsConnection.getInstance(); - private WebappInterceptNavigationDelegate.CustomTabTimeSpentLogger mWebappTimeSpentLogger; + private WebappCustomTabTimeSpentLogger mWebappTimeSpentLogger; private static class PageLoadMetricsObserver implements PageLoadMetrics.Observer { private final CustomTabsConnection mConnection; @@ -727,11 +727,9 @@ } } mIsInitialResume = false; - mWebappTimeSpentLogger = - WebappInterceptNavigationDelegate.CustomTabTimeSpentLogger - .createInstanceAndStartTimer(getIntent().getIntExtra( - CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, - ACTIVITY_TYPE_OTHER)); + mWebappTimeSpentLogger = WebappCustomTabTimeSpentLogger.createInstanceAndStartTimer( + getIntent().getIntExtra(CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, + ACTIVITY_TYPE_OTHER)); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java index b73bc73d..fa697225 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java
@@ -9,6 +9,7 @@ import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.webapps.WebappScopePolicy; import java.util.List; @@ -30,10 +31,12 @@ boolean willChromeHandleIntent(Intent intent); /** - * Returns true if the current activity is a webapp and {@params url} lies within the scope of - * that webapp. + * If the current activity is a webapp, applies the webapp's scope policy and returns the + * result. Returns {@link WebappScopePolicy#NavigationDirective#NORMAL_BEHAVIOR} if the current + * activity is not a webapp. */ - boolean isWithinCurrentWebappScope(String url); + @WebappScopePolicy.NavigationDirective + int applyWebappScopePolicyForUrl(String url); /** * Returns the number of specialized intent handlers in {@params infos}. Specialized intent @@ -102,6 +105,13 @@ void startFileIntent(Intent intent, String referrerUrl, Tab tab, boolean needsToCloseTab); /** + * Launches a Chrome Custom Tab to be shown on top of a WebappActivity. + * @param url + * @param launchInNewTask Whether the CCT should be launched in a new task. + */ + void launchCctForWebappUrl(String url, boolean launchInNewTask); + + /** * Clobber the current tab and try not to pass an intent when it should be handled by Chrome * so that we can deliver HTTP referrer information safely. *
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 45a62010..ebbb979 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
@@ -19,6 +19,7 @@ import android.os.StrictMode; import android.provider.Browser; import android.provider.Telephony; +import android.support.customtabs.CustomTabsIntent; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.view.WindowManager.BadTokenException; @@ -48,6 +49,7 @@ import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.chrome.browser.webapps.WebappActivity; +import org.chromium.chrome.browser.webapps.WebappScopePolicy; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationEntry; @@ -254,13 +256,14 @@ } @Override - public boolean isWithinCurrentWebappScope(String url) { + public @WebappScopePolicy.NavigationDirective int applyWebappScopePolicyForUrl(String url) { Context context = getAvailableContext(); if (context instanceof WebappActivity) { - String scope = ((WebappActivity) context).getWebappScope(); - return url.startsWith(scope); + WebappActivity webappActivity = (WebappActivity) context; + return webappActivity.scopePolicy().applyPolicyForNavigationToUrl( + webappActivity.getWebappInfo(), url); } - return false; + return WebappScopePolicy.NavigationDirective.NORMAL_BEHAVIOR; } @Override @@ -520,6 +523,17 @@ } @Override + public void launchCctForWebappUrl(String url, boolean launchInNewTask) { + Context context = getAvailableContext(); + if (!(context instanceof WebappActivity)) return; + + CustomTabsIntent customTabIntent = + ((WebappActivity) context).buildCustomTabIntentForURL(url); + if (launchInNewTask) customTabIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + customTabIntent.launchUrl(context, Uri.parse(url)); + } + + @Override public OverrideUrlLoadingResult clobberCurrentTab( String url, String referrerUrl, final Tab tab) { int transitionType = PageTransition.LINK;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java index dd8c01b1..8584da1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.tab.TabRedirectHandler; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.chrome.browser.util.UrlUtilities; +import org.chromium.chrome.browser.webapps.WebappScopePolicy; import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.ui.base.PageTransition; @@ -275,12 +276,6 @@ } } - // http://crbug.com/647569 : Stay in a PWA window for a URL within the same scope. - if (mDelegate.isWithinCurrentWebappScope(params.getUrl())) { - if (DEBUG) Log.i(TAG, "NO_OVERRIDE: Stay in PWA window"); - return OverrideUrlLoadingResult.NO_OVERRIDE; - } - // http://crbug.com/181186: We need to show the intent picker when we receive a redirect // following a form submit. boolean isRedirectFromFormSubmit = isFormSubmit && params.isRedirect(); @@ -356,6 +351,15 @@ return OverrideUrlLoadingResult.NO_OVERRIDE; } + // http://crbug.com/647569 : Stay in a PWA window for a URL within the same scope. + @WebappScopePolicy.NavigationDirective + int webappScopePolicyDirective = mDelegate.applyWebappScopePolicyForUrl(params.getUrl()); + if (webappScopePolicyDirective + == WebappScopePolicy.NavigationDirective.IGNORE_EXTERNAL_INTENT_REQUESTS) { + if (DEBUG) Log.i(TAG, "NO_OVERRIDE: Stay in PWA window"); + return OverrideUrlLoadingResult.NO_OVERRIDE; + } + // Sanitize the Intent, ensuring web pages can not bypass browser // security (only access to BROWSABLE activities). intent.addCategory(Intent.CATEGORY_BROWSABLE); @@ -446,6 +450,23 @@ return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT; } + // For normal links in a webapp, launch a CCT when a user navigates to a link which + // is outside of the webapp's scope. This is the preferred handling for when a user + // navigates outside of a webapp's scope. The benefit of showing out-of-scope web + // content in a CCT is that the state of the in-scope page (e.g. scroll position) is + // preserved and is available when the user closes the CCT. This enables the state + // of the twitter.com web page to be preserved when a user taps an out-of-scope + // link. WebappActivity has fallback behavior for cases that a CCT is not launched + // (e.g. JS navigation when PWA is in the background). The fallback behavior changes + // the appearance of the WebappActivity to make it look like a CCT. + if (webappScopePolicyDirective + == WebappScopePolicy.NavigationDirective.LAUNCH_CCT) { + mDelegate.launchCctForWebappUrl(params.getUrl(), + params.shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent()); + if (DEBUG) Log.i(TAG, "OVERRIDE_WITH_EXTERNAL_INTENT: Launch CCT"); + return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT; + } + if (DEBUG) Log.i(TAG, "NO_OVERRIDE: No specialized handler for URL"); return OverrideUrlLoadingResult.NO_OVERRIDE; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java index 740ec18..cf702d0a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -34,6 +34,7 @@ import android.util.SparseArray; import android.view.KeyEvent; +import org.chromium.base.CollectionUtil; import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.SysUtils; @@ -1216,7 +1217,7 @@ compactActions.add(actions.indexOf(MediaSessionAction.PLAY)); } compactActions.add(actions.indexOf(CUSTOM_MEDIA_SESSION_ACTION_STOP)); - return convertIntegerListToIntArray(compactActions); + return CollectionUtil.integerListToIntArray(compactActions); } int[] actionsArray = new int[COMPACT_VIEW_ACTIONS_COUNT]; @@ -1245,12 +1246,6 @@ return actionsArray; } - static int[] convertIntegerListToIntArray(List<Integer> intList) { - int[] intArray = new int[intList.size()]; - for (int i = 0; i < intList.size(); ++i) intArray[i] = i; - return intArray; - } - private static Context getContext() { return ContextUtils.getApplicationContext(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java index 5040411..c781fb4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java
@@ -29,6 +29,7 @@ import android.widget.ListView; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.CollectionUtil; import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; @@ -260,14 +261,6 @@ } } - private int[] toIntArray(List<Integer> boxedList) { - int[] result = new int[boxedList.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = boxedList.get(i); - } - return result; - } - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // We check the domains and urls as well due to crbug.com/622879. @@ -312,10 +305,11 @@ } } data.putExtra(DESELECTED_DOMAINS_TAG, deselectedDomains.toArray(new String[0])); - data.putExtra( - DESELECTED_DOMAIN_REASONS_TAG, toIntArray(deselectedDomainReasons)); + data.putExtra(DESELECTED_DOMAIN_REASONS_TAG, + CollectionUtil.integerListToIntArray(deselectedDomainReasons)); data.putExtra(IGNORED_DOMAINS_TAG, ignoredDomains.toArray(new String[0])); - data.putExtra(IGNORED_DOMAIN_REASONS_TAG, toIntArray(ignoredDomainReasons)); + data.putExtra(IGNORED_DOMAIN_REASONS_TAG, + CollectionUtil.integerListToIntArray(ignoredDomainReasons)); getTargetFragment().onActivityResult( getTargetRequestCode(), Activity.RESULT_OK, data); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java index 56720dc..902f969 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
@@ -229,7 +229,7 @@ return mTab.getWebContents().getNavigationController().getLastCommittedEntryIndex(); } - protected boolean shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent() { + private boolean shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent() { if (mTab.getWebContents() == null) return false; if (!mTab.getWebContents().getNavigationController().canGoToOffset(0)) return true; @@ -248,7 +248,7 @@ * Called when Chrome decides to override URL loading and launch an intent or an asynchronous * action. */ - protected void onOverrideUrlLoadingAndLaunchIntent() { + private void onOverrideUrlLoadingAndLaunchIntent() { if (mTab.getWebContents() == null) return; // Before leaving Chrome, close the empty child tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java index 35a8a11..0a2ebadb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -105,7 +105,7 @@ protected void onUpdatedLastUsedTime( WebappDataStorage storage, boolean previouslyLaunched, long previousUsageTimestamp) { if (previouslyLaunched) { - WebApkUma.recordLaunchInterval(storage.getLastUsedTime() - previousUsageTimestamp); + WebApkUma.recordLaunchInterval(storage.getLastUsedTimeMs() - previousUsageTimestamp); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index e67dedc..e235112 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -16,8 +16,10 @@ import android.os.Bundle; import android.os.StrictMode; import android.os.SystemClock; +import android.provider.Browser; import android.support.annotation.IntDef; import android.support.annotation.Nullable; +import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsService; import android.support.customtabs.CustomTabsSessionToken; import android.support.customtabs.TrustedWebUtils; @@ -47,6 +49,7 @@ import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.customtabs.CustomTabAppMenuPropertiesDelegate; +import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.document.DocumentUtils; @@ -600,7 +603,7 @@ // with the heuristic. if (mWebappInfo.isLaunchedFromHomescreen()) { boolean previouslyLaunched = storage.hasBeenLaunched(); - long previousUsageTimestamp = storage.getLastUsedTime(); + long previousUsageTimestamp = storage.getLastUsedTimeMs(); storage.setHasBeenLaunched(); // TODO(yusufo): WebappRegistry#unregisterOldWebapps uses this information to delete // WebappDataStorage objects for legacy webapps which haven't been used in a while. @@ -718,7 +721,7 @@ }; } - protected WebappScopePolicy scopePolicy() { + public WebappScopePolicy scopePolicy() { return isVerified() ? WebappScopePolicy.STRICT : WebappScopePolicy.LEGACY; } @@ -764,6 +767,23 @@ getBrowserSession()); } + public CustomTabsIntent buildCustomTabIntentForURL(String url) { + CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); + intentBuilder.setShowTitle(true); + if (mWebappInfo.hasValidThemeColor()) { + // Need to cast as themeColor is a long to contain possible error results. + intentBuilder.setToolbarColor((int) mWebappInfo.themeColor()); + } + CustomTabsIntent customTabIntent = intentBuilder.build(); + customTabIntent.intent.setPackage(getPackageName()); + customTabIntent.intent.putExtra( + CustomTabIntentDataProvider.EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER, true); + customTabIntent.intent.putExtra( + CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, getActivityType()); + customTabIntent.intent.putExtra(Browser.EXTRA_APPLICATION_ID, mWebappInfo.apkPackageName()); + return customTabIntent; + } + private void updateToolbarCloseButtonVisibility() { if (WebappBrowserControlsDelegate.shouldShowToolbarCloseButton(this)) { getToolbarManager().setCloseButtonDrawable(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappCustomTabTimeSpentLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappCustomTabTimeSpentLogger.java new file mode 100644 index 0000000..2c608840 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappCustomTabTimeSpentLogger.java
@@ -0,0 +1,56 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.webapps; + +import android.os.SystemClock; + +import org.chromium.base.metrics.RecordHistogram; + +import java.util.concurrent.TimeUnit; + +/** Logs to UMA the amount of time user spends in a CCT for CCTs launched from webapps. */ +public class WebappCustomTabTimeSpentLogger { + private long mStartTime; + private @WebappActivity.ActivityType int mActivityType; + + private WebappCustomTabTimeSpentLogger(@WebappActivity.ActivityType int activityType) { + mActivityType = activityType; + mStartTime = SystemClock.elapsedRealtime(); + } + + /** + * Create {@link WebappCustomTabTimeSpentLogger} instance and starts timer. + * @param type of the activity that opens the CCT. + * @return {@link WebappCustomTabTimeSpentLogger} instance. + */ + public static WebappCustomTabTimeSpentLogger createInstanceAndStartTimer( + @WebappActivity.ActivityType int activityType) { + return new WebappCustomTabTimeSpentLogger(activityType); + } + + /** + * Stop timer and log UMA. + */ + public void onPause() { + long timeSpent = SystemClock.elapsedRealtime() - mStartTime; + String umaSuffix; + switch (mActivityType) { + case WebappActivity.ACTIVITY_TYPE_WEBAPP: + umaSuffix = ".Webapp"; + break; + case WebappActivity.ACTIVITY_TYPE_WEBAPK: + umaSuffix = ".WebApk"; + break; + case WebappActivity.ACTIVITY_TYPE_TWA: + umaSuffix = ".TWA"; + break; + default: + umaSuffix = ".Other"; + break; + } + RecordHistogram.recordLongTimesHistogram( + "CustomTab.SessionDuration" + umaSuffix, timeSpent, TimeUnit.MILLISECONDS); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java index 5a4d33f3..f828afb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -305,7 +305,7 @@ */ public boolean wasUsedRecently() { // WebappRegistry.register sets the last used time, so that counts as a 'launch'. - return (sClock.currentTimeMillis() - getLastUsedTime() < WEBAPP_LAST_OPEN_MAX_TIME); + return (sClock.currentTimeMillis() - getLastUsedTimeMs() < WEBAPP_LAST_OPEN_MAX_TIME); } /** @@ -368,9 +368,9 @@ } /** - * Returns the last used time of this object, or -1 if it is not stored. + * Returns the last used time, in milliseconds, of this object, or -1 if it is not stored. */ - public long getLastUsedTime() { + public long getLastUsedTimeMs() { return mPreferences.getLong(KEY_LAST_USED, TIMESTAMP_INVALID); } @@ -419,10 +419,10 @@ } /** - * Returns the completion time of the last check for whether the WebAPK's Web Manifest was - * updated. This time needs to be set when the WebAPK is registered. + * Returns the completion time, in milliseconds, of the last check for whether the WebAPK's Web + * Manifest was updated. This time needs to be set when the WebAPK is registered. */ - private long getLastCheckForWebManifestUpdateTime() { + private long getLastCheckForWebManifestUpdateTimeMs() { return mPreferences.getLong(KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME, TIMESTAMP_INVALID); } @@ -436,10 +436,10 @@ } /** - * Returns when the last WebAPK update request completed (successfully or unsuccessfully). - * This time needs to be set when the WebAPK is registered. + * Returns the time, in milliseconds, that the last WebAPK update request completed + * (successfully or unsuccessfully). This time needs to be set when the WebAPK is registered. */ - long getLastWebApkUpdateRequestCompletionTime() { + long getLastWebApkUpdateRequestCompletionTimeMs() { return mPreferences.getLong(KEY_LAST_UPDATE_REQUEST_COMPLETE_TIME, TIMESTAMP_INVALID); } @@ -480,7 +480,7 @@ * been any update attempts. */ boolean didPreviousUpdateSucceed() { - long lastUpdateCompletionTime = getLastWebApkUpdateRequestCompletionTime(); + long lastUpdateCompletionTime = getLastWebApkUpdateRequestCompletionTimeMs(); if (lastUpdateCompletionTime == TIMESTAMP_INVALID) { return true; } @@ -538,7 +538,7 @@ * last {@link numMillis} milliseconds. */ boolean wasCheckForUpdatesDoneInLastMs(long numMillis) { - return (sClock.currentTimeMillis() - getLastCheckForWebManifestUpdateTime()) < numMillis; + return (sClock.currentTimeMillis() - getLastCheckForWebManifestUpdateTimeMs()) < numMillis; } /** Returns whether we should check for update. */ @@ -546,10 +546,10 @@ long checkUpdatesInterval = shouldRelaxUpdates() ? RELAXED_UPDATE_INTERVAL : UPDATE_INTERVAL; long now = sClock.currentTimeMillis(); - long sinceLastCheckDurationMs = now - getLastCheckForWebManifestUpdateTime(); + long sinceLastCheckDurationMs = now - getLastCheckForWebManifestUpdateTimeMs(); if (sinceLastCheckDurationMs >= checkUpdatesInterval) return true; - long sinceLastUpdateRequestDurationMs = now - getLastWebApkUpdateRequestCompletionTime(); + long sinceLastUpdateRequestDurationMs = now - getLastWebApkUpdateRequestCompletionTimeMs(); return sinceLastUpdateRequestDurationMs >= RETRY_UPDATE_DURATION && !didPreviousUpdateSucceed(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java index dd828c4..206ce803 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java
@@ -14,7 +14,6 @@ import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.fullscreen.ComposedBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate; -import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabContextMenuItemDelegate; import org.chromium.chrome.browser.tab.TabDelegateFactory; @@ -89,11 +88,6 @@ } @Override - public InterceptNavigationDelegateImpl createInterceptNavigationDelegate(Tab tab) { - return new WebappInterceptNavigationDelegate(mActivity, tab); - } - - @Override public boolean canShowAppBanners(Tab tab) { // Do not show banners when we are in a standalone activity. return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInterceptNavigationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInterceptNavigationDelegate.java deleted file mode 100644 index a70cc02..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInterceptNavigationDelegate.java +++ /dev/null
@@ -1,135 +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. - -package org.chromium.chrome.browser.webapps; - -import android.net.Uri; -import android.os.SystemClock; -import android.provider.Browser; -import android.support.customtabs.CustomTabsIntent; - -import org.chromium.base.metrics.RecordHistogram; -import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; -import org.chromium.chrome.browser.externalnav.ExternalNavigationParams; -import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tab.TabRedirectHandler; -import org.chromium.chrome.browser.util.UrlUtilities; -import org.chromium.components.navigation_interception.NavigationParams; - -import java.util.concurrent.TimeUnit; - -/** - * Intercepts navigations made by the Web App and sends off-origin http(s) ones to a Custom Tab. - */ -public class WebappInterceptNavigationDelegate extends InterceptNavigationDelegateImpl { - /** - * Log the time spent on CCT opened by WebappActivity. - */ - public static class CustomTabTimeSpentLogger { - private long mStartTime; - private @WebappActivity.ActivityType int mActivityType; - - private CustomTabTimeSpentLogger(@WebappActivity.ActivityType int activityType) { - mActivityType = activityType; - mStartTime = SystemClock.elapsedRealtime(); - } - - /** - * Create {@link CustomTabTimeSpentLogger} instance and start timer if activity type is one - * of WebAPP, WebApk and Trusted Web Activity, - * @param type of the activity that opens the CCT. - * @return {@link CustomTabTimeSpentLogger} instance if activity is WebAPP/WebApk/TWA, - * otherwise null. - */ - public static CustomTabTimeSpentLogger createInstanceAndStartTimer( - @WebappActivity.ActivityType int activityType) { - return new CustomTabTimeSpentLogger(activityType); - } - - /** - * Stop timer and log uma. - */ - public void onPause() { - long timeSpent = SystemClock.elapsedRealtime() - mStartTime; - String umaSuffix; - switch (mActivityType) { - case WebappActivity.ACTIVITY_TYPE_WEBAPP: - umaSuffix = ".Webapp"; - break; - case WebappActivity.ACTIVITY_TYPE_WEBAPK: - umaSuffix = ".WebApk"; - break; - case WebappActivity.ACTIVITY_TYPE_TWA: - umaSuffix = ".TWA"; - break; - default: - umaSuffix = ".Other"; - break; - } - RecordHistogram.recordLongTimesHistogram( - "CustomTab.SessionDuration" + umaSuffix, timeSpent, TimeUnit.MILLISECONDS); - } - } - - private final WebappActivity mActivity; - - public WebappInterceptNavigationDelegate(WebappActivity activity, Tab tab) { - super(tab); - this.mActivity = activity; - } - - @Override - public boolean shouldIgnoreNavigation(NavigationParams navigationParams) { - if (super.shouldIgnoreNavigation(navigationParams)) { - return true; - } - - if (shouldOpenInCustomTab( - navigationParams, mActivity.getWebappInfo(), mActivity.scopePolicy())) { - CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); - intentBuilder.setShowTitle(true); - if (mActivity.getWebappInfo().hasValidThemeColor()) { - // Need to cast as themeColor is a long to contain possible error results. - intentBuilder.setToolbarColor((int) mActivity.getWebappInfo().themeColor()); - } - CustomTabsIntent customTabIntent = intentBuilder.build(); - customTabIntent.intent.setPackage(mActivity.getPackageName()); - customTabIntent.intent.putExtra( - CustomTabIntentDataProvider.EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER, true); - customTabIntent.intent.putExtra(CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, - mActivity.getActivityType()); - customTabIntent.intent.putExtra( - Browser.EXTRA_APPLICATION_ID, mActivity.getWebappInfo().apkPackageName()); - - if (shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent()) { - customTabIntent.intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK); - } - customTabIntent.launchUrl(mActivity, Uri.parse(navigationParams.url)); - - onOverrideUrlLoadingAndLaunchIntent(); - return true; - } - - return false; - } - - @Override - public ExternalNavigationParams.Builder buildExternalNavigationParams( - NavigationParams navigationParams, TabRedirectHandler tabRedirectHandler, - boolean shouldCloseTab) { - ExternalNavigationParams.Builder builder = super.buildExternalNavigationParams( - navigationParams, tabRedirectHandler, shouldCloseTab); - builder.setNativeClientPackageName(mActivity.getNativeClientPackageName()); - return builder; - } - - static boolean shouldOpenInCustomTab( - NavigationParams navigationParams, WebappInfo info, WebappScopePolicy scopePolicy) { - return UrlUtilities.isValidForIntentFallbackNavigation(navigationParams.url) - && !navigationParams.isPost && navigationParams.suggestedFilename == null - && !scopePolicy.isUrlInScope(info, navigationParams.url) - && scopePolicy.openOffScopeNavsInCct(); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java index fa4f33f..f820fa5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -120,7 +120,7 @@ // Access the WebappDataStorage to force it to finish loading. A strict mode // exception is thrown if the WebappDataStorage is accessed on the UI thread prior // to the storage being fully loaded. - storage.getLastUsedTime(); + storage.getLastUsedTimeMs(); return storage; } @@ -235,7 +235,7 @@ && isWebApkInstalled(webApkPackage)) { continue; } - } else if ((currentTime - storage.getLastUsedTime()) + } else if ((currentTime - storage.getLastUsedTimeMs()) < WEBAPP_UNOPENED_CLEANUP_DURATION) { continue; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappScopePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappScopePolicy.java index 79785f1..fa74fef8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappScopePolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappScopePolicy.java
@@ -3,12 +3,17 @@ // found in the LICENSE file. package org.chromium.chrome.browser.webapps; +import android.support.annotation.IntDef; + import org.chromium.chrome.browser.util.UrlUtilities; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Defines which URLs are inside a web app scope as well as what to do when user navigates to them. */ -enum WebappScopePolicy { +public enum WebappScopePolicy { LEGACY { @Override public boolean isUrlInScope(WebappInfo info, String url) { @@ -16,7 +21,7 @@ } @Override - public boolean openOffScopeNavsInCct() { + protected boolean openOffScopeNavsInCct() { // This is motivated by redirect based OAuth. Legacy web apps cannot capture in-scope // URLs to WebappActivity. Redirect based OAuth therefore would move the user to CCT // and keeps them there even after redirecting back to in-scope URL. @@ -31,11 +36,23 @@ } @Override - public boolean openOffScopeNavsInCct() { + protected boolean openOffScopeNavsInCct() { return true; } }; + @Retention(RetentionPolicy.SOURCE) + @IntDef({NavigationDirective.NORMAL_BEHAVIOR, + NavigationDirective.IGNORE_EXTERNAL_INTENT_REQUESTS, NavigationDirective.LAUNCH_CCT}) + public @interface NavigationDirective { + // No special handling. + int NORMAL_BEHAVIOR = 0; + // The navigation should stay in the webapp. External intent handlers should be ignored. + int IGNORE_EXTERNAL_INTENT_REQUESTS = 1; + // The navigation should launch a CCT. + int LAUNCH_CCT = 2; + } + /** * @return {@code true} if given {@code url} is in scope of a web app as defined by its * {@code WebappInfo}, {@code false} otherwise. @@ -46,5 +63,13 @@ * @return {@code true} if off-scope URLs should be handled by the Chrome Custom Tab, * {@code false} otherwise. */ - abstract boolean openOffScopeNavsInCct(); + protected abstract boolean openOffScopeNavsInCct(); + + /** Applies the scope policy for navigation to {@link url}. */ + public @NavigationDirective int applyPolicyForNavigationToUrl(WebappInfo info, String url) { + if (isUrlInScope(info, url)) return NavigationDirective.IGNORE_EXTERNAL_INTENT_REQUESTS; + + return openOffScopeNavsInCct() ? NavigationDirective.LAUNCH_CCT + : NavigationDirective.NORMAL_BEHAVIOR; + } }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index b4792db..3678611 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1333,11 +1333,11 @@ "java/src/org/chromium/chrome/browser/webapps/WebappActivity9.java", "java/src/org/chromium/chrome/browser/webapps/WebappAuthenticator.java", "java/src/org/chromium/chrome/browser/webapps/WebappBrowserControlsDelegate.java", + "java/src/org/chromium/chrome/browser/webapps/WebappCustomTabTimeSpentLogger.java", "java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java", "java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java", "java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java", "java/src/org/chromium/chrome/browser/webapps/WebappInfo.java", - "java/src/org/chromium/chrome/browser/webapps/WebappInterceptNavigationDelegate.java", "java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java", "java/src/org/chromium/chrome/browser/webapps/WebappManagedActivity.java", "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java index 77cc321..8dc7e2e8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -30,6 +30,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.banners.InstallerDelegateTest.TestPackageManager; @@ -38,6 +39,8 @@ import org.chromium.chrome.browser.instantapps.InstantAppsHandler; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabRedirectHandler; +import org.chromium.chrome.browser.webapps.WebappInfo; +import org.chromium.chrome.browser.webapps.WebappScopePolicy; import org.chromium.content.browser.test.NativeLibraryTestRule; import org.chromium.ui.base.PageTransition; import org.chromium.webapk.lib.common.WebApkConstants; @@ -61,9 +64,10 @@ private static final int START_INCOGNITO = 0x1; private static final int START_WEBAPK = 0x2; private static final int START_FILE = 0x4; - private static final int START_OTHER_ACTIVITY = 0x8; - private static final int INTENT_SANITIZATION_EXCEPTION = 0x10; - private static final int PROXY_FOR_INSTANT_APPS = 0x20; + private static final int START_WEBAPP_CCT = 0x8; + private static final int START_OTHER_ACTIVITY = 0x10; + private static final int INTENT_SANITIZATION_EXCEPTION = 0x20; + private static final int PROXY_FOR_INSTANT_APPS = 0x40; private static final String SEARCH_RESULT_URL_FOR_TOM_HANKS = "https://www.google.com/search?q=tom+hanks"; @@ -276,16 +280,6 @@ @Test @SmallTest - public void testInWebapp() { - mDelegate.add(new IntentActivity(YOUTUBE_URL, YOUTUBE_PACKAGE_NAME)); - - // Don't override if the URL is within the current webapp scope. - mDelegate.setIsWithinCurrentWebappScope(true); - checkUrl(YOUTUBE_URL).expecting(OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); - } - - @Test - @SmallTest public void testWtai() { // Start the telephone application with the given number. checkUrl("wtai://wp/mc;0123456789") @@ -1248,22 +1242,78 @@ } /** - * Test that tapping on a link which is outside of the referrer WebAPK's scope keeps the user in - * the WebAPK. (A minibar with the URL should show though). + * Test that tapping a link which falls into the scope of the current webapp keeps the user in + * the webapp. */ @Test @SmallTest - public void testLeaveWebApk_LinkOutOfScope() { - mDelegate.add(new IntentActivity(WEBAPK_SCOPE, WEBAPK_PACKAGE_NAME).withIsWebApk(true)); + public void testLaunchWebApp_StayInSameWebApp() { + final String twaScope = "https://my_twa.org"; + final String twaPackageName = "org.my_twa"; + mDelegate.add(new IntentActivity(twaScope, twaPackageName) + .withWebappScopePolicy(WebappScopePolicy.STRICT)); + mDelegate.setReferrerWebappPackageName(twaPackageName); + + checkUrl(twaScope + "/new.html").expecting(OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); + } + + /** + * Test that when a webapp with "STRICT scope policy" is navigated outside of the webapp's scope + * by "tapping a link" that a Chrome Custom Tab is launched. + */ + @Test + @SmallTest + public void testLeaveStrictWebapp_LinkOutOfScope() { + final String twaScope = "https://my_twa.org"; + final String twaPackageName = "org.my_twa"; + mDelegate.add(new IntentActivity(twaScope, twaPackageName) + .withWebappScopePolicy(WebappScopePolicy.STRICT)); + mDelegate.setReferrerWebappPackageName(twaPackageName); checkUrl(SEARCH_RESULT_URL_FOR_TOM_HANKS) - .withWebApkPackageName(WEBAPK_PACKAGE_NAME) + .expecting( + OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, START_WEBAPP_CCT); + } + + /** + * Test that when a webapp with "STRICT scope policy" is navigated outside of the webapp's scope + * via "JavaScript while the webapp is in the background" that a CCT is not launched (as not to + * move the webapp to the foreground and annoy the user) + */ + @Test + @SmallTest + public void testLeaveStrictWebapp_JSBackgroundNavOutOfScope() { + final String twaScope = "https://my_twa.org"; + final String twaPackageName = "org.my_twa"; + mDelegate.add(new IntentActivity(twaScope, twaPackageName) + .withWebappScopePolicy(WebappScopePolicy.STRICT)); + mDelegate.setReferrerWebappPackageName(twaPackageName); + + checkUrl(SEARCH_RESULT_URL_FOR_TOM_HANKS) + .withIsBackgroundTabNavigation(true) + .expecting(OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); + } + + /** + * Test that when a webapp with "LEGACY scope policy" is navigated outside of the webapp's scope + * by "tapping a link" that a CCT is not launched. + */ + @Test + @SmallTest + public void testLeaveLegacyWebapp_LinkOutOfScope() { + final String twaScope = "https://my_twa.org"; + final String twaPackageName = "org.my_twa"; + mDelegate.add(new IntentActivity(twaScope, twaPackageName) + .withWebappScopePolicy(WebappScopePolicy.LEGACY)); + mDelegate.setReferrerWebappPackageName(twaPackageName); + + checkUrl(SEARCH_RESULT_URL_FOR_TOM_HANKS) .expecting(OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); } /** * Test that tapping a link which falls solely in the scope of a WebAPK launches a WebAPK - * without showing the intent picker if WebAPKs are enabled. + * without showing the intent picker. */ @Test @SmallTest @@ -1304,10 +1354,10 @@ mDelegate.add(new IntentActivity(scope1, scope1WebApkPackageName).withIsWebApk(true)); mDelegate.add(new IntentActivity(scope1, scope1NativeAppPackageName)); mDelegate.add(new IntentActivity(scope2, WEBAPK_PACKAGE_NAME).withIsWebApk(true)); + mDelegate.setReferrerWebappPackageName(scope1WebApkPackageName); checkUrl(scope2) .withReferrer(scope1) - .withWebApkPackageName(scope1WebApkPackageName) .expecting(OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, START_WEBAPK); } @@ -1325,20 +1375,6 @@ START_OTHER_ACTIVITY); } - /** - * Test that tapping a link which falls into the scope of the current WebAPK keeps the user in - * the WebAPK. - */ - @Test - @SmallTest - public void testLaunchWebApk_StayInSameWebApk() { - mDelegate.add(new IntentActivity(WEBAPK_SCOPE, WEBAPK_PACKAGE_NAME).withIsWebApk(true)); - - checkUrl(WEBAPK_SCOPE + "/new.html") - .withWebApkPackageName(WEBAPK_PACKAGE_NAME) - .expecting(OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); - } - private static ResolveInfo newResolveInfo(String packageName) { ActivityInfo ai = new ActivityInfo(); ai.packageName = packageName; @@ -1348,18 +1384,31 @@ return ri; } + private static WebappInfo newWebappInfoFromScope(String scope) { + return WebappInfo.create("", "", scope, null, null, null, WebDisplayMode.STANDALONE, 0, 0, + 0, 0, null, false, false); + } + private static class IntentActivity { - public String mUrlPrefix; - public String mPackageName; - public boolean mIsWebApk; + private String mUrlPrefix; + private String mPackageName; + private boolean mIsWebApk; + private WebappScopePolicy mWebappScopePolicy; public IntentActivity(String urlPrefix, String packageName) { mUrlPrefix = urlPrefix; mPackageName = packageName; + mWebappScopePolicy = WebappScopePolicy.LEGACY; } public IntentActivity withIsWebApk(boolean isWebApk) { mIsWebApk = isWebApk; + mWebappScopePolicy = WebappScopePolicy.STRICT; + return this; + } + + public IntentActivity withWebappScopePolicy(WebappScopePolicy policy) { + mWebappScopePolicy = policy; return this; } @@ -1375,6 +1424,10 @@ return mIsWebApk; } + public WebappScopePolicy webappScopePolicy() { + return mWebappScopePolicy; + } + public boolean isSpecialized() { // Specialized if URL prefix is more than just a scheme. return Pattern.compile("[^:/]+://.+").matcher(mUrlPrefix).matches(); @@ -1416,8 +1469,15 @@ } @Override - public boolean isWithinCurrentWebappScope(String url) { - return mIsWithinCurrentWebappScope; + public @WebappScopePolicy.NavigationDirective int applyWebappScopePolicyForUrl(String url) { + for (IntentActivity intentActivity : mIntentActivities) { + if (intentActivity.packageName().equals(mReferrerWebappPackageName)) { + WebappInfo info = newWebappInfoFromScope(intentActivity.urlPrefix()); + return intentActivity.webappScopePolicy().applyPolicyForNavigationToUrl( + info, url); + } + } + return WebappScopePolicy.NavigationDirective.NORMAL_BEHAVIOR; } @Override @@ -1490,6 +1550,11 @@ } @Override + public void launchCctForWebappUrl(String url, boolean launchInNewTask) { + startWebappCctIntentCalled = true; + } + + @Override public OverrideUrlLoadingResult clobberCurrentTab( String url, String referrerUrl, Tab tab) { mNewUrlAfterClobbering = url; @@ -1540,6 +1605,7 @@ startActivityIntent = null; startIncognitoIntentCalled = false; startFileIntentCalled = false; + startWebappCctIntentCalled = false; mCalledWithProxy = false; } @@ -1563,8 +1629,12 @@ mIsChromeAppInForeground = value; } - public void setIsWithinCurrentWebappScope(boolean value) { - mIsWithinCurrentWebappScope = value; + public void setReferrerWebappPackageName(String webappPackageName) { + mReferrerWebappPackageName = webappPackageName; + } + + public String getReferrerWebappPackageName() { + return mReferrerWebappPackageName; } public void setCanHandleWithInstantApp(boolean value) { @@ -1581,8 +1651,13 @@ public Intent startActivityIntent; public boolean startIncognitoIntentCalled; + public boolean startFileIntentCalled; + public boolean startWebappCctIntentCalled; + public String defaultSmsPackageName; - public ArrayList<IntentActivity> mIntentActivities = new ArrayList<IntentActivity>(); + private String mReferrerWebappPackageName; + + private ArrayList<IntentActivity> mIntentActivities = new ArrayList<IntentActivity>(); private boolean mCanResolveActivityForExternalSchemes = true; private String mNewUrlAfterClobbering; private String mReferrerUrlForClobbering; @@ -1591,11 +1666,8 @@ private String mPreviousUrl; public boolean mCalledWithProxy; public boolean mIsChromeAppInForeground = true; - public boolean mIsWithinCurrentWebappScope; public boolean shouldRequestFileAccess; - public boolean startFileIntentCalled; - public String defaultSmsPackageName; } private void checkIntentSanity(Intent intent, String name) { @@ -1618,7 +1690,6 @@ private boolean mIsRedirect; private boolean mChromeAppInForegroundRequired = true; private boolean mIsBackgroundTabNavigation; - private String mWebApkPackageName; private boolean mHasUserGesture; private TabRedirectHandler mRedirectHandler; @@ -1626,11 +1697,6 @@ mUrl = url; } - public ExternalNavigationTestParams withWebApkPackageName(String webApkPackageName) { - mWebApkPackageName = webApkPackageName; - return this; - } - public ExternalNavigationTestParams withReferrer(String referrerUrl) { mReferrerUrl = referrerUrl; return this; @@ -1674,6 +1740,7 @@ boolean expectStartActivity = (otherExpectation & (START_WEBAPK | START_OTHER_ACTIVITY)) != 0; boolean expectStartWebApk = (otherExpectation & START_WEBAPK) != 0; + boolean expectStartWebappCct = (otherExpectation & START_WEBAPP_CCT) != 0; boolean expectStartOtherActivity = (otherExpectation & START_OTHER_ACTIVITY) != 0; boolean expectStartFile = (otherExpectation & START_FILE) != 0; boolean expectSaneIntent = expectStartOtherActivity @@ -1689,7 +1756,7 @@ .setRedirectHandler(mRedirectHandler) .setIsBackgroundTabNavigation(mIsBackgroundTabNavigation) .setIsMainFrame(true) - .setNativeClientPackageName(mWebApkPackageName) + .setNativeClientPackageName(mDelegate.getReferrerWebappPackageName()) .setHasUserGesture(mHasUserGesture) .build(); OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params); @@ -1706,6 +1773,7 @@ Assert.assertEquals(expectedOverrideResult, result); Assert.assertEquals(expectStartIncognito, mDelegate.startIncognitoIntentCalled); + Assert.assertEquals(expectStartWebappCct, mDelegate.startWebappCctIntentCalled); Assert.assertEquals(expectStartActivity, startActivityCalled); Assert.assertEquals(expectStartWebApk, startWebApkCalled); Assert.assertEquals(expectStartFile, mDelegate.startFileIntentCalled);
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 a337026..f47aef0 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
@@ -172,7 +172,7 @@ WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage("first"); Assert.assertEquals("", storage.getScope()); Assert.assertEquals("", storage.getUrl()); - Assert.assertEquals(0, storage.getLastUsedTime()); + Assert.assertEquals(0, storage.getLastUsedTimeMs()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java index 2669508..08602cf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
@@ -20,6 +20,7 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import java.util.concurrent.Callable; @@ -83,15 +84,6 @@ setGeolocation(DSE_ORIGIN, null, ContentSetting.DEFAULT, incognito); Assert.assertEquals(ContentSetting.ALLOW, getGeolocation(DSE_ORIGIN, null, incognito)); - // Resetting an embedded DSE origin should not have the same behavior. - incognito = false; - setGeolocation(DSE_ORIGIN, OTHER_ORIGIN, ContentSetting.BLOCK, incognito); - Assert.assertEquals( - ContentSetting.BLOCK, getGeolocation(DSE_ORIGIN, OTHER_ORIGIN, incognito)); - setGeolocation(DSE_ORIGIN, OTHER_ORIGIN, ContentSetting.DEFAULT, incognito); - Assert.assertEquals( - ContentSetting.ASK, getGeolocation(DSE_ORIGIN, OTHER_ORIGIN, incognito)); - // Resetting in incognito should not have the same behavior. incognito = true; setGeolocation(DSE_ORIGIN, null, ContentSetting.BLOCK, incognito); @@ -110,6 +102,23 @@ @Test @SmallTest @Feature({"Preferences"}) + @DisableFeatures(ChromeFeatureList.PERMISSION_DELEGATION) + public void testResetDSEGeolocationEmbeddedOrigin() throws Throwable { + // It's not possible to set a permission for an embedded origin when permission delegation + // is enabled. This code can be deleted when the feature is enabled by default. + // Resetting an embedded DSE origin should not have the same behavior. + boolean incognito = false; + setGeolocation(DSE_ORIGIN, OTHER_ORIGIN, ContentSetting.BLOCK, incognito); + Assert.assertEquals( + ContentSetting.BLOCK, getGeolocation(DSE_ORIGIN, OTHER_ORIGIN, incognito)); + setGeolocation(DSE_ORIGIN, OTHER_ORIGIN, ContentSetting.DEFAULT, incognito); + Assert.assertEquals( + ContentSetting.ASK, getGeolocation(DSE_ORIGIN, OTHER_ORIGIN, incognito)); + } + + @Test + @SmallTest + @Feature({"Preferences"}) @EnableFeatures(ChromeFeatureList.GRANT_NOTIFICATIONS_TO_DSE) public void testResetDSENotifications() throws Throwable { // On Android O+ we need to clear notification channels so they don't interfere with the
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java index af7a6bd5..5290fca8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java
@@ -183,7 +183,7 @@ Assert.assertEquals(0, RecordHistogram.getHistogramTotalCountForTesting(histogramName)); WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage( WebApkConstants.WEBAPK_ID_PREFIX + packageName); - Assert.assertNotEquals(WebappDataStorage.TIMESTAMP_INVALID, storage.getLastUsedTime()); + Assert.assertNotEquals(WebappDataStorage.TIMESTAMP_INVALID, storage.getLastUsedTimeMs()); } /** Test that the "WebApk.LaunchInterval" histogram is recorded on susbequent launches. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java index 47276b7..3ea64842c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -43,7 +43,6 @@ import org.chromium.chrome.test.util.MenuUtils; import org.chromium.chrome.test.util.browser.WebappTestPage; import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils; -import org.chromium.components.navigation_interception.NavigationParams; import org.chromium.content.browser.test.NativeLibraryTestRule; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; @@ -181,6 +180,40 @@ } /** + * Test that navigating outside of the webapp scope as a result of submitting a form with method + * "POST": + * - Shows a CCT-like webapp toolbar. + * - Preserves the theme color specified in the launch intent. + */ + @Test + @SmallTest + @Feature({"Webapps"}) + @RetryOnFailure + public void testFormSubmitOffOrigin() throws Exception { + Intent launchIntent = mActivityTestRule.createIntent().putExtra( + ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN); + mActivityTestRule.addTwaExtrasToIntent(launchIntent); + + WebappActivity activity = runWebappActivityAndWaitForIdle(launchIntent); + + mActivityTestRule.runJavaScriptCodeInCurrentTab( + String.format("var formTag = document.createElement('form');" + + "formTag.id = 'post_form';" + + "formTag.setAttribute('method', 'post');" + + "formTag.setAttribute('action', '%s');" + + "document.body.appendChild(formTag);" + + "var buttonTag = document.createElement('input');" + + "buttonTag.id = 'post_button';" + + "buttonTag.setAttribute('type', 'submit');" + + "formTag.appendChild(buttonTag);", + offOriginUrl())); + clickNodeWithId("post_button"); + + ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), offOriginUrl()); + Assert.assertEquals(Color.CYAN, activity.getToolbarManager().getPrimaryColor()); + } + + /** * Test that navigating outside of the webapp scope by tapping a link with target="_blank": * - Launches a CCT. * - The CCT toolbar does not use the webapp theme colour. @@ -245,8 +278,7 @@ + "};" + "document.body.appendChild(aTag);", offOriginUrl())); - DOMUtils.clickNode( - mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); + clickNodeWithId("testId"); CustomTabActivity customTab = waitFor(CustomTabActivity.class); ChromeTabUtils.waitForTabPageLoaded(customTab.getActivityTab(), offOriginUrl()); @@ -428,37 +460,6 @@ ChromeTabUtils.waitForTabPageLoaded(activity.getActivityTab(), initialInScopeUrl); } - @Test - @SmallTest - @Feature({"Webapps"}) - public void testPostRequestIsNotHandledByCct() throws Exception { - mNativeLibraryTestRule.loadNativeLibraryNoBrowserProcess(); - // Post requests should never be opened in CCT. See crbug/771984 - // This test is poking at WebappInterceptNavigationDelegate directly, - // as it's hard to test WebAPKs as well as to stub responses to POST requests. - WebApkInfo info = WebApkInfo.create("", "https://somewebapp.com", "https://somewebapp.com", - null, null, null, null, WebDisplayMode.STANDALONE, 0, 0, 0, 0, "", 0, null, "", - null, false /* forceNavigation */); - - // Note that isPost is the only field being different between the two calls. - Assert.assertFalse(WebappInterceptNavigationDelegate.shouldOpenInCustomTab( - NavigationParams.create("https://otherdomain.com", - "https://somewebapp.com" /* referrer */, true /* isPost */, - true /* hasUserGesture */, PageTransition.FORM_SUBMIT, - false /* isRedirect */, false /* isExternalProtocol */, - true /* isMainFrame */, null /* suggestedFilename */, - true /* hasUserGestureCarryover */), - info, WebappScopePolicy.STRICT)); - Assert.assertTrue(WebappInterceptNavigationDelegate.shouldOpenInCustomTab( - NavigationParams.create("https://otherdomain.com", - "https://somewebapp.com" /* referrer */, false /* isPost */, - true /* hasUserGesture */, PageTransition.FORM_SUBMIT, - false /* isRedirect */, false /* isExternalProtocol */, - true /* isMainFrame */, null /* suggestedFilename */, - true /* hasUserGestureCarryover */), - info, WebappScopePolicy.STRICT)); - } - private WebappActivity runWebappActivityAndWaitForIdle(Intent intent) throws Exception { mActivityTestRule.startWebappActivity(intent.putExtra(ShortcutHelper.EXTRA_URL, WebappTestPage.getServiceWorkerUrl(mActivityTestRule.getTestServer()))); @@ -496,10 +497,14 @@ id, url, target)); } + private void clickNodeWithId(String id) throws Exception { + DOMUtils.clickNode( + mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), id); + } + private void addAnchorAndClick(String url, String target) throws Exception { addAnchor("testId", url, target); - DOMUtils.clickNode( - mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); + clickNodeWithId("testId"); } @SuppressWarnings("unchecked")
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java index f4049de4..573520073 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -433,7 +433,7 @@ WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME); assertTrue(storage.getDidLastWebApkUpdateRequestSucceed()); - assertEquals(initialTime, storage.getLastWebApkUpdateRequestCompletionTime()); + assertEquals(initialTime, storage.getLastWebApkUpdateRequestCompletionTimeMs()); } /** @@ -456,8 +456,8 @@ assertFalse(updateManager.updateRequested()); assertTrue(storage.getDidLastWebApkUpdateRequestSucceed()); - assertEquals( - mClockRule.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime()); + assertEquals(mClockRule.currentTimeMillis(), + storage.getLastWebApkUpdateRequestCompletionTimeMs()); } /** @@ -480,8 +480,8 @@ // Check {@link WebappDataStorage} state. WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME); assertFalse(storage.getDidLastWebApkUpdateRequestSucceed()); - assertEquals( - mClockRule.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime()); + assertEquals(mClockRule.currentTimeMillis(), + storage.getLastWebApkUpdateRequestCompletionTimeMs()); } /**
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java index 22c989d64..3630096 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -99,7 +99,7 @@ public void testLastUsedRetrieval() throws Exception { long lastUsed = 100; mSharedPreferences.edit().putLong(WebappDataStorage.KEY_LAST_USED, lastUsed).apply(); - assertEquals(lastUsed, new WebappDataStorage("test").getLastUsedTime()); + assertEquals(lastUsed, new WebappDataStorage("test").getLastUsedTimeMs()); } @Test
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 6adb6eb4..91648dc 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-66.0.3356.0_rc-r1.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-66.0.3357.0_rc-r1.afdo.bz2 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b6a0e23..a8d310e 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -317,18 +317,6 @@ <message name="IDS_DISABLE" desc="Used for Disable on buttons"> Disable </message> - <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU" desc="The name of the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> - Writing Direction - </message> - <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT" desc="The name of the 'default' item from the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> - Default - </message> - <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR" desc="The name of the 'Left to Right' item from the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> - Left to Right - </message> - <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL" desc="The name of the 'Right to Left' item from the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> - Right to Left - </message> <!-- Search strings are only used in webui, so no mobile. --> <if expr="not is_android"> <message name="IDS_SEARCH_RESULTS" desc="Message announced to screenreader users when searching completes and results are showing."> @@ -4512,6 +4500,9 @@ <message name="IDS_HOSTED_APP_NAME_AND_DOMAIN" desc="The string that is always displayed in the window title in Hosted App app windows."> <ph name="APP_NAME">$1<ex>GMail</ex></ph> by <ph name="SITE_ORIGIN">$2<ex>google.com</ex></ph> </message> + <message name="IDS_HOSTED_APPMENU_TOOLTIP"> + Customize and control <ph name="APP_NAME">$1<ex>GMail</ex></ph> + </message> <!-- Components --> <message name="IDS_COMPONENTS_TITLE" desc="Title for the chrome://components page.">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 679662fa..b8e750a 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -3904,31 +3904,37 @@ </message> </if> - <!-- Incompatible Software Page --> + <!-- Incompatible Applications Page --> <if expr="is_win and _google_chrome"> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_RESET_CARD_TITLE" desc="The title of the Incompatible Software section of the settings."> - Update or remove incompatible software + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_RESET_CARD_TITLE" desc="The title of the Incompatible Applications section of the settings."> + Update or remove incompatible applications </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_SUBPAGE_SUBTITLE" desc="The subtitle shown in the subpage for incompatible software."> - The following software could be preventing Chrome from working properly. + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE" desc="The subtitle shown in the subpage for incompatible applications."> + {NUM_APPLICATIONS, plural, + =1 {The following application could be preventing Chrome from working properly.} + other {The following applications could be preventing Chrome from working properly.}} </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_SUBPAGE_SUBTITLE_NO_ADMIN_RIGHTS" desc="The subtitle shown in the subpage for incompatible software, when the user does not have administrator rights. This means that these users are incapable of updating or removing incompatible software by themselves."> - To ensure that you can keep browsing the web, ask your administrator to remove this software. + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE_NO_ADMIN_RIGHTS" desc="The subtitle shown in the subpage for incompatible applications, when the user does not have administrator rights. This means that these users are incapable of updating or removing incompatible applications by themselves."> + {NUM_APPLICATIONS, plural, + =1 {To ensure that you can keep browsing the web, ask your administrator to remove this application.} + other {To ensure that you can keep browsing the web, ask your administrator to remove these applications.}} </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_SUBPAGE_LEARN_HOW" desc="Following the subtitle, this is a link to a help center article that explains how to update any program."> - <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn how to update software<ph name="END_LINK"></a></ph> + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_LEARN_HOW" desc="Following the subtitle, this is a link to a help center article that explains how to update any program."> + <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn how to update applications<ph name="END_LINK"></a></ph> </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_LIST_TITLE" desc="This is the title for the list of incompatible software."> - Software + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_LIST_TITLE" desc="This is the title for the list of incompatible applications."> + {NUM_APLLICATIONS, plural, + =1 {Application} + other {Applications}} </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_REMOVE_BUTTON" desc="The label of the button if the recommended action for this software is to uninstall it."> + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_REMOVE_BUTTON" desc="The label of the button if the recommended action for this application is to uninstall it."> Remove... </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_UPDATE_BUTTON" desc="The label of the button if the recommended action for this software is to update it."> + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_UPDATE_BUTTON" desc="The label of the button if the recommended action for this application is to update it."> Update </message> - <message name="IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_DONE" desc="This message is displayed when the Incompatible Software section is empty. This is possible when the user starts interacting with the section and update/remove the software in the list."> - Done! No incompatible software found. + <message name="IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_DONE" desc="This message is displayed when the Incompatible Applications section is empty. This is possible when the user starts interacting with the section and update/remove the applications in the list."> + Done! No incompatible applications found. </message> </if> </grit-part>
diff --git a/chrome/app/theme/default_100_percent/common/favicon_bookmarks.png b/chrome/app/theme/default_100_percent/common/favicon_bookmarks.png index b220d7c4..d9bce44 100644 --- a/chrome/app/theme/default_100_percent/common/favicon_bookmarks.png +++ b/chrome/app/theme/default_100_percent/common/favicon_bookmarks.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_conflicts.png b/chrome/app/theme/default_100_percent/common/favicon_conflicts.png index fbd60c4..51331b6 100644 --- a/chrome/app/theme/default_100_percent/common/favicon_conflicts.png +++ b/chrome/app/theme/default_100_percent/common/favicon_conflicts.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_downloads.png b/chrome/app/theme/default_100_percent/common/favicon_downloads.png index 0f8838f..d0b7b56 100644 --- a/chrome/app/theme/default_100_percent/common/favicon_downloads.png +++ b/chrome/app/theme/default_100_percent/common/favicon_downloads.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_extensions.png b/chrome/app/theme/default_100_percent/common/favicon_extensions.png index e4a6522..b845820 100644 --- a/chrome/app/theme/default_100_percent/common/favicon_extensions.png +++ b/chrome/app/theme/default_100_percent/common/favicon_extensions.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_print_preview.png b/chrome/app/theme/default_100_percent/common/favicon_print_preview.png index 5bdb469..d5701ed 100644 --- a/chrome/app/theme/default_100_percent/common/favicon_print_preview.png +++ b/chrome/app/theme/default_100_percent/common/favicon_print_preview.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/favicon_settings.png b/chrome/app/theme/default_100_percent/common/favicon_settings.png index 1767934..d35b668 100644 --- a/chrome/app/theme/default_100_percent/common/favicon_settings.png +++ b/chrome/app/theme/default_100_percent/common/favicon_settings.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png b/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png index b420608..1d1c1e8 100644 --- a/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png +++ b/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/favicon_phone.png b/chrome/app/theme/default_100_percent/legacy/favicon_phone.png index 90e5b524..7489a78 100644 --- a/chrome/app/theme/default_100_percent/legacy/favicon_phone.png +++ b/chrome/app/theme/default_100_percent/legacy/favicon_phone.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png b/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png index 84217a9..c1458f1 100644 --- a/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png +++ b/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png b/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png index f6684d7..68a557e 100644 --- a/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png +++ b/chrome/app/theme/default_200_percent/common/favicon_bookmarks.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_conflicts.png b/chrome/app/theme/default_200_percent/common/favicon_conflicts.png index 7694a51..4811680 100644 --- a/chrome/app/theme/default_200_percent/common/favicon_conflicts.png +++ b/chrome/app/theme/default_200_percent/common/favicon_conflicts.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_downloads.png b/chrome/app/theme/default_200_percent/common/favicon_downloads.png index 32c4802..f2323553 100644 --- a/chrome/app/theme/default_200_percent/common/favicon_downloads.png +++ b/chrome/app/theme/default_200_percent/common/favicon_downloads.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_extensions.png b/chrome/app/theme/default_200_percent/common/favicon_extensions.png index f893e3e1..12fbd41 100644 --- a/chrome/app/theme/default_200_percent/common/favicon_extensions.png +++ b/chrome/app/theme/default_200_percent/common/favicon_extensions.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_print_preview.png b/chrome/app/theme/default_200_percent/common/favicon_print_preview.png index e3efff2..f1ffe64 100644 --- a/chrome/app/theme/default_200_percent/common/favicon_print_preview.png +++ b/chrome/app/theme/default_200_percent/common/favicon_print_preview.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_settings.png b/chrome/app/theme/default_200_percent/common/favicon_settings.png index 73fb82d..2a92c3a 100644 --- a/chrome/app/theme/default_200_percent/common/favicon_settings.png +++ b/chrome/app/theme/default_200_percent/common/favicon_settings.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png b/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png index e9c35b1..3eb7409 100644 --- a/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png +++ b/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/favicon_phone.png b/chrome/app/theme/default_200_percent/legacy/favicon_phone.png index 03f2e6a5..35b7847 100644 --- a/chrome/app/theme/default_200_percent/legacy/favicon_phone.png +++ b/chrome/app/theme/default_200_percent/legacy/favicon_phone.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png b/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png index 49d13a9..ac453a6 100644 --- a/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png +++ b/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png Binary files differ
diff --git a/chrome/app/vector_icons/profile_switcher_outline.icon b/chrome/app/vector_icons/profile_switcher_outline.icon index 11b0d52b..80cd26b 100644 --- a/chrome/app/vector_icons/profile_switcher_outline.icon +++ b/chrome/app/vector_icons/profile_switcher_outline.icon
@@ -5,7 +5,7 @@ // This is a copy of account_circle.icon with an added path for an outline. // Outline: STROKE, 3, -PATH_COLOR_ARGB, 0xff, 0x5a, 0x5a, 0x5a, +PATH_COLOR_ARGB, 0xff, 0x75, 0x75, 0x75, MOVE_TO, 24, 4, CUBIC_TO, 12.95f, 4, 4, 12.95f, 4, 24, R_CUBIC_TO, 0, 11.05f, 8.95f, 20, 20, 20,
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 3a4e4cf..38823d76 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2120,6 +2120,10 @@ {"enable-desktop-pwas", flag_descriptions::kEnableDesktopPWAsName, flag_descriptions::kEnableDesktopPWAsDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kDesktopPWAWindowing)}, + {"enable-desktop-pwas-link-capturing", + flag_descriptions::kEnableDesktopPWAsLinkCapturingName, + flag_descriptions::kEnableDesktopPWAsLinkCapturingDescription, kOsDesktop, + FEATURE_VALUE_TYPE(features::kDesktopPWAsLinkCapturing)}, {"use-sync-sandbox", flag_descriptions::kSyncSandboxName, flag_descriptions::kSyncSandboxDescription, kOsAll, SINGLE_VALUE_TYPE_AND_VALUE(
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index c93606d9..e2794893 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -47,6 +47,7 @@ &features::kDownloadsLocationChange, &features::kImportantSitesInCbd, &features::kMaterialDesignIncognitoNTP, + &features::kPermissionDelegation, &features::kServiceWorkerPaymentApps, &features::kSiteNotificationChannels, &features::kSimplifiedFullscreenUI,
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index ac97a4d..e7a7440 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -1833,17 +1833,8 @@ NO_TEST_SERVER); } -// Flaky on Chromium OS: https://crbug.com/814040 -#if defined(OS_CHROMEOS) -#define MAYBE_Shim_TestResizeWebviewWithDisplayNoneResizesContent \ - DISABLED_Shim_TestResizeWebviewWithDisplayNoneResizesContent -#else -#define MAYBE_Shim_TestResizeWebviewWithDisplayNoneResizesContent \ - Shim_TestResizeWebviewWithDisplayNoneResizesContent -#endif -IN_PROC_BROWSER_TEST_P( - WebViewSizeTest, - MAYBE_Shim_TestResizeWebviewWithDisplayNoneResizesContent) { +IN_PROC_BROWSER_TEST_P(WebViewSizeTest, + Shim_TestResizeWebviewWithDisplayNoneResizesContent) { TestHelper("testResizeWebviewWithDisplayNoneResizesContent", "web_view/shim", NO_TEST_SERVER);
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index 72d95c6..516b78b0 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -81,6 +81,7 @@ #include "content/public/test/mock_download_manager.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" +#include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_store.h" #include "net/http/http_transaction_factory.h" #include "net/net_features.h" @@ -251,9 +252,9 @@ new content::MessageLoopRunner; quit_closure_ = message_loop_runner->QuitClosure(); get_cookie_success_ = false; - cookie_store_->GetCookiesWithOptionsAsync( + cookie_store_->GetCookieListWithOptionsAsync( kOrigin1, net::CookieOptions(), - base::BindOnce(&RemoveCookieTester::GetCookieCallback, + base::BindOnce(&RemoveCookieTester::GetCookieListCallback, base::Unretained(this))); message_loop_runner->Run(); return get_cookie_success_; @@ -276,11 +277,13 @@ } private: - void GetCookieCallback(const std::string& cookies) { - if (cookies == "A=1") { + void GetCookieListCallback(const net::CookieList& cookie_list) { + std::string cookie_line = + net::CanonicalCookie::BuildCookieLine(cookie_list); + if (cookie_line == "A=1") { get_cookie_success_ = true; } else { - EXPECT_EQ("", cookies); + EXPECT_EQ("", cookie_line); get_cookie_success_ = false; } quit_closure_.Run();
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 2ff1117..e5813f3f 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1402,6 +1402,8 @@ "power/ml/idle_event_notifier.h", "power/ml/real_boot_clock.cc", "power/ml/real_boot_clock.h", + "power/ml/recent_events_counter.cc", + "power/ml/recent_events_counter.h", "power/ml/user_activity_logger.cc", "power/ml/user_activity_logger.h", "power/ml/user_activity_logger_delegate.h", @@ -1982,6 +1984,7 @@ "power/ml/fake_boot_clock.h", "power/ml/idle_event_notifier_unittest.cc", "power/ml/real_boot_clock_unittest.cc", + "power/ml/recent_events_counter_unittest.cc", "power/ml/user_activity_logger_delegate_ukm_unittest.cc", "power/ml/user_activity_logger_unittest.cc", "power/power_data_collector_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc index 60af6bb1..5f89bec 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
@@ -318,7 +318,7 @@ // expected behavior. auto it2 = notification_key_to_tree_.find(kNotificationKey); EXPECT_NE(notification_key_to_tree_.end(), it2); - AXTreeSourceArc* tree2 = it->second.get(); + AXTreeSourceArc* tree2 = it2->second.get(); ui::AXTreeData tree_data2; tree2->GetTreeData(&tree_data2); EXPECT_EQ(tree_data2.tree_id, test_surface.GetAXTreeId());
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc index 40a50db..2d16187 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -194,7 +194,13 @@ &chrome_role)) { ax::mojom::Role role_value = ui::ParseRole(chrome_role.c_str()); if (role_value != ax::mojom::Role::kNone) { - out_data->role = role_value; + // The webView and rootWebArea roles differ between Android and Chrome. In + // particular, Android includes far fewer attributes which leads to + // undesirable behavior. Exclude their direct mapping. + out_data->role = (role_value != ax::mojom::Role::kWebView && + role_value != ax::mojom::Role::kRootWebArea) + ? role_value + : ax::mojom::Role::kGenericContainer; return; } } @@ -236,7 +242,6 @@ MAP_ROLE(ui::kAXToggleButtonClassname, ax::mojom::Role::kToggleButton); MAP_ROLE(ui::kAXViewClassname, ax::mojom::Role::kGenericContainer); MAP_ROLE(ui::kAXViewGroupClassname, ax::mojom::Role::kGroup); - MAP_ROLE(ui::kAXWebViewClassname, ax::mojom::Role::kWebView); #undef MAP_ROLE
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc index 0456bf90..189991d 100644 --- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc +++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
@@ -142,7 +142,7 @@ // TODO(crbug.com/776464): Replace |CanSetUserWallpaper| with mojo callback. if (!wallpaper_controller->CanSetUserWallpaper(account.id, - !account.is_ephemeral)) { + account.is_ephemeral)) { // When kiosk app is running or policy is enforced, WallpaperController // doesn't process custom wallpaper requests. service_->NotifyWallpaperChangedAndReset(android_id_);
diff --git a/chrome/browser/chromeos/eol_notification.cc b/chrome/browser/chromeos/eol_notification.cc index 53d698e..a7eae6d 100644 --- a/chrome/browser/chromeos/eol_notification.cc +++ b/chrome/browser/chromeos/eol_notification.cc
@@ -104,8 +104,8 @@ DBusThreadManager::Get()->GetUpdateEngineClient(); // Request the Eol Status. - update_engine_client->GetEolStatus( - base::Bind(&EolNotification::OnEolStatus, weak_factory_.GetWeakPtr())); + update_engine_client->GetEolStatus(base::BindOnce( + &EolNotification::OnEolStatus, weak_factory_.GetWeakPtr())); } void EolNotification::OnEolStatus(update_engine::EndOfLifeStatus status) {
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc index b384ec53..16af64c 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
@@ -318,13 +318,13 @@ ->ShouldSetDevicePolicyWallpaper(); } - // Obtain WallpaperInfo for |user_number| from WallpaperManager. + // A wrapper of |WallpaperController::GetUserWallpaperInfo|. void GetUserWallpaperInfo(int user_number, wallpaper::WallpaperInfo* wallpaper_info) { ash::Shell::Get()->wallpaper_controller()->GetUserWallpaperInfo( testUsers_[user_number], wallpaper_info, - !user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( - testUsers_[user_number]) /*is_persistent=*/); + user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( + testUsers_[user_number]) /*is_ephemeral=*/); } base::FilePath test_data_dir_;
diff --git a/chrome/browser/chromeos/power/ml/recent_events_counter.cc b/chrome/browser/chromeos/power/ml/recent_events_counter.cc new file mode 100644 index 0000000..af85a75 --- /dev/null +++ b/chrome/browser/chromeos/power/ml/recent_events_counter.cc
@@ -0,0 +1,87 @@ +// 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/chromeos/power/ml/recent_events_counter.h" + +#include "base/logging.h" + +namespace chromeos { +namespace power { +namespace ml { + +RecentEventsCounter::RecentEventsCounter(base::TimeDelta duration, + int num_buckets) + : duration_(duration), num_buckets_(num_buckets) { + DCHECK_GT(num_buckets_, 0); + bucket_duration_ = duration_ / num_buckets_; + event_count_.resize(num_buckets_, 0); +} + +RecentEventsCounter::~RecentEventsCounter() = default; + +void RecentEventsCounter::Log(base::TimeDelta timestamp) { + if (timestamp < first_bucket_time_) { + // This event is too old to log. + return; + } + if (timestamp > latest_) { + latest_ = timestamp; + } + int bucket_index = GetBucketIndex(timestamp); + if (timestamp < first_bucket_time_ + duration_) { + // The event is within the current time window so increment the bucket. + event_count_[bucket_index]++; + return; + } + + // The event is later than the current window for the existing data. + event_count_[bucket_index] = 1; + + for (int i = first_bucket_index_; i != bucket_index; + i = (i + 1) % num_buckets_) { + event_count_[i] = 0; + } + first_bucket_index_ = (bucket_index + 1) % num_buckets_; + + int num_cycles = floor(timestamp / duration_); + base::TimeDelta cycle_start = num_cycles * duration_; + int extra_buckets = floor((timestamp - cycle_start) / bucket_duration_); + first_bucket_time_ = cycle_start + extra_buckets * bucket_duration_ + + bucket_duration_ - duration_; +} + +int RecentEventsCounter::GetTotal(base::TimeDelta now) { + DCHECK_GE(now, latest_); + if (now >= first_bucket_time_ + 2 * duration_) { + return 0; + } + int total = 0; + base::TimeDelta start = + std::max(first_bucket_time_, now - duration_ + bucket_duration_); + base::TimeDelta end = + std::min(now + bucket_duration_, first_bucket_time_ + duration_); + int end_index = GetBucketIndex(end); + for (int i = GetBucketIndex(start); i != end_index; + i = (i + 1) % num_buckets_) { + total += event_count_[i]; + } + return total; +} + +int RecentEventsCounter::GetBucketIndex(base::TimeDelta timestamp) const { + DCHECK_GE(timestamp, base::TimeDelta()); + + int num_cycles = floor(timestamp / duration_); + base::TimeDelta cycle_start = num_cycles * duration_; + int index = floor((timestamp - cycle_start) / bucket_duration_); + if (index >= num_buckets_) { + return num_buckets_ - 1; + } + DCHECK_GE(index, 0); + return index; +} + +} // namespace ml +} // namespace power +} // namespace chromeos
diff --git a/chrome/browser/chromeos/power/ml/recent_events_counter.h b/chrome/browser/chromeos/power/ml/recent_events_counter.h new file mode 100644 index 0000000..4b998f9 --- /dev/null +++ b/chrome/browser/chromeos/power/ml/recent_events_counter.h
@@ -0,0 +1,71 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POWER_ML_RECENT_EVENTS_COUNTER_H_ +#define CHROME_BROWSER_CHROMEOS_POWER_ML_RECENT_EVENTS_COUNTER_H_ + +#include <vector> + +#include "base/time/time.h" + +namespace chromeos { +namespace power { +namespace ml { + +// RecentEventsCounter keeps a running count of events that occurred in the last +// |duration| period of time. For example, a count of the number of events in +// the last hour. +// +// Rather than remembering the time stamp for each event, the event times are +// bucketed. The buckets initially evenly divide a time period of |duration_|, +// starting at base::TimeDelta(). For logging at a time later than |duration_|, +// the buckets are reused, using the logging time modulo the |duration_| in the +// calculation of the bucket to be used. The total is calculated by keeping +// track of the |first_bucket_index_| and |first_bucket_time_| and zeroing +// buckets with stale data. +// +// The bucketing determines the time precision of the count. This +// means that the actual time period counted may be up to one bucket length +// shorter than the requested time period. It will never be longer than the +// requested time period. +class RecentEventsCounter { + public: + // Count events for a time period of length |duration| using + // |num_buckets| buckets. + RecentEventsCounter(base::TimeDelta duration, int num_buckets); + ~RecentEventsCounter(); + + // Log an event at timedelta |timestamp|. |timestamp| cannot be negative. + void Log(base::TimeDelta timestamp); + + // Return the count of events reported in the |duration_| preceeding |now|. + int GetTotal(base::TimeDelta now); + + private: + // Return the index of the bucket containing |timestamp|. + int GetBucketIndex(base::TimeDelta timestamp) const; + + // The length of time that events should be recorded. + base::TimeDelta duration_; + // The number of buckets to use to record the events. + int num_buckets_; + // The number of events in each bucket. + std::vector<int> event_count_; + // The index of the first bucket. |event_count_| is a circular array. + int first_bucket_index_ = 0; + // The starting time of the first bucket. + base::TimeDelta first_bucket_time_; + // The duration of each bucket. + base::TimeDelta bucket_duration_; + // The latest timedelta that has been logged. + base::TimeDelta latest_; + + DISALLOW_COPY_AND_ASSIGN(RecentEventsCounter); +}; + +} // namespace ml +} // namespace power +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_POWER_ML_RECENT_EVENTS_COUNTER_H_
diff --git a/chrome/browser/chromeos/power/ml/recent_events_counter_unittest.cc b/chrome/browser/chromeos/power/ml/recent_events_counter_unittest.cc new file mode 100644 index 0000000..c1deb42 --- /dev/null +++ b/chrome/browser/chromeos/power/ml/recent_events_counter_unittest.cc
@@ -0,0 +1,52 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/power/ml/recent_events_counter.h" + +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace power { +namespace ml { + +TEST(RecentEventsCounterTest, TimeTest) { + base::TimeDelta minute = base::TimeDelta::FromMinutes(1); + RecentEventsCounter counter(base::TimeDelta::FromHours(1), 60); + ASSERT_EQ(counter.GetTotal(minute), 0); + + counter.Log(5 * minute); + ASSERT_EQ(counter.GetTotal(10 * minute), 1); + + counter.Log(5 * minute); + ASSERT_EQ(counter.GetTotal(10 * minute), 2); + + counter.Log(25.4 * minute); + + ASSERT_EQ(counter.GetTotal(30 * minute), 3); + ASSERT_EQ(counter.GetTotal(70 * minute), 1); + // Event at 25.4 minutes is counted 59 minutes later. + ASSERT_EQ(counter.GetTotal(84.4 * minute), 1); + // Event at 25.4 minutes is not counted 59.7 minutes later at 85.1 minutes. An + // an event logged at 85.1 minutes would wipe out the event at 25.4 minutes, + // so the event at 25.4 minutes cannot be counted to ensure consistency. + ASSERT_EQ(counter.GetTotal(85.1 * minute), 0); + + counter.Log(75 * minute); + ASSERT_EQ(counter.GetTotal(80 * minute), 2); + ASSERT_EQ(counter.GetTotal(90 * minute), 1); + + // Overwrite the 25.4 minute logging. + counter.Log(85.1 * minute); + ASSERT_EQ(counter.GetTotal(90 * minute), 2); + + counter.Log(200 * minute); + ASSERT_EQ(counter.GetTotal(210 * minute), 1); + + ASSERT_EQ(counter.GetTotal(300 * minute), 0); +} + +} // namespace ml +} // namespace power +} // namespace chromeos
diff --git a/chrome/browser/chromeos/power/ml/user_activity_event.proto b/chrome/browser/chromeos/power/ml/user_activity_event.proto index ccd15ba2..24c4cc9 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_event.proto +++ b/chrome/browser/chromeos/power/ml/user_activity_event.proto
@@ -137,7 +137,12 @@ optional int32 video_playing_time_sec = 16; // Duration from the time video ended to the time of idle event. optional int32 time_since_video_ended_sec = 17; - } // next id = 18 + + // Number of key/mouse/touch events in the past hour. + optional int32 key_events_in_last_hour = 18; + optional int32 mouse_events_in_last_hour = 19; + optional int32 touch_events_in_last_hour = 20; + } // next id = 21 optional ModelParams params = 1; optional Event event = 2;
diff --git a/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.cc b/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.cc index 9253c11..85aa51d 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.cc +++ b/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.cc
@@ -24,11 +24,19 @@ namespace { +constexpr UserActivityLoggerDelegateUkm::Bucket kBatteryPercentBuckets[] = { + {100, 5}}; + constexpr UserActivityLoggerDelegateUkm::Bucket kEventLogDurationBuckets[] = { {60, 1}, {300, 10}, {600, 20}}; +constexpr UserActivityLoggerDelegateUkm::Bucket kUserInputEventBuckets[] = { + {100, 1}, + {1000, 100}, + {10000, 1000}}; + constexpr UserActivityLoggerDelegateUkm::Bucket kRecentVideoPlayingTimeBuckets[] = {{60, 1}, {1200, 300}, @@ -44,23 +52,15 @@ } // namespace -// static -int UserActivityLoggerDelegateUkm::BucketEveryFivePercents(int original_value) { +int UserActivityLoggerDelegateUkm::Bucketize(int original_value, + const Bucket* buckets, + size_t num_buckets) { DCHECK_GE(original_value, 0); - DCHECK_LE(original_value, 100); - return 5 * (original_value / 5); -} - -int UserActivityLoggerDelegateUkm::ExponentiallyBucketTimestamp( - int timestamp_sec, - const Bucket* buckets, - size_t num_buckets) { - DCHECK_GE(timestamp_sec, 0); DCHECK(buckets); for (size_t i = 0; i < num_buckets; ++i) { const Bucket& bucket = buckets[i]; - if (timestamp_sec < bucket.boundary_end) { - return bucket.rounding * (timestamp_sec / bucket.rounding); + if (original_value < bucket.boundary_end) { + return bucket.rounding * (original_value / bucket.rounding); } } return buckets[num_buckets - 1].boundary_end; @@ -138,19 +138,19 @@ user_activity.SetSequenceId(next_sequence_id_++) .SetDeviceMode(event.features().device_mode()) .SetDeviceType(event.features().device_type()) - .SetEventLogDuration(ExponentiallyBucketTimestamp( - event.event().log_duration_sec(), kEventLogDurationBuckets, - arraysize(kEventLogDurationBuckets))) + .SetEventLogDuration(Bucketize(event.event().log_duration_sec(), + kEventLogDurationBuckets, + arraysize(kEventLogDurationBuckets))) .SetEventReason(event.event().reason()) .SetEventType(event.event().type()) .SetLastActivityDay(event.features().last_activity_day()) .SetLastActivityTime( std::floor(event.features().last_activity_time_sec() / 3600)) .SetRecentTimeActive(event.features().recent_time_active_sec()) - .SetRecentVideoPlayingTime(ExponentiallyBucketTimestamp( - event.features().video_playing_time_sec(), - kRecentVideoPlayingTimeBuckets, - arraysize(kRecentVideoPlayingTimeBuckets))); + .SetRecentVideoPlayingTime( + Bucketize(event.features().video_playing_time_sec(), + kRecentVideoPlayingTimeBuckets, + arraysize(kRecentVideoPlayingTimeBuckets))); if (event.features().has_on_to_dim_sec()) { user_activity.SetScreenDimDelay(event.features().on_to_dim_sec()); @@ -178,8 +178,9 @@ } if (event.features().has_battery_percent()) { - user_activity.SetBatteryPercent(BucketEveryFivePercents( - std::floor(event.features().battery_percent()))); + user_activity.SetBatteryPercent( + Bucketize(std::floor(event.features().battery_percent()), + kBatteryPercentBuckets, arraysize(kBatteryPercentBuckets))); } if (event.features().has_device_management()) { @@ -187,10 +188,28 @@ } if (event.features().has_time_since_video_ended_sec()) { - user_activity.SetTimeSinceLastVideoEnded(ExponentiallyBucketTimestamp( - event.features().time_since_video_ended_sec(), - kTimeSinceLastVideoEndedBuckets, - arraysize(kTimeSinceLastVideoEndedBuckets))); + user_activity.SetTimeSinceLastVideoEnded( + Bucketize(event.features().time_since_video_ended_sec(), + kTimeSinceLastVideoEndedBuckets, + arraysize(kTimeSinceLastVideoEndedBuckets))); + } + + if (event.features().has_key_events_in_last_hour()) { + user_activity.SetKeyEventsInLastHour( + Bucketize(event.features().key_events_in_last_hour(), + kUserInputEventBuckets, arraysize(kUserInputEventBuckets))); + } + + if (event.features().has_mouse_events_in_last_hour()) { + user_activity.SetMouseEventsInLastHour( + Bucketize(event.features().mouse_events_in_last_hour(), + kUserInputEventBuckets, arraysize(kUserInputEventBuckets))); + } + + if (event.features().has_touch_events_in_last_hour()) { + user_activity.SetTouchEventsInLastHour( + Bucketize(event.features().touch_events_in_last_hour(), + kUserInputEventBuckets, arraysize(kUserInputEventBuckets))); } user_activity.Record(ukm_recorder_);
diff --git a/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.h b/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.h index a93ea567..4377707 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.h +++ b/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm.h
@@ -18,29 +18,24 @@ class UserActivityLoggerDelegateUkm : public UserActivityLoggerDelegate { public: - // Places |original_value| into buckets of size 5, i.e. if |original_value| is - // in [0, 5), we map it 0; if it is in [5, 10), we map it to 5 etc. - // |original_value| should be in the range of [0, 100]. - static int BucketEveryFivePercents(int original_value); - - // Both |boundary_end| and |rounding| are seconds. + // Both |boundary_end| and |rounding| must be positive. struct Bucket { int boundary_end; int rounding; }; - // Bucket |timestamp_sec| using given |buckets|, which is an array of - // Bucket and must be sorted in ascending order of - // |boundary_end|. An example - // of |buckets| is {{60, 1}, {300, 10}, {600, 20}}. This function looks for - // the first |boundary_end| > |timestamp_sec| and bucket it to the nearest - // |rounding|. If |timestamp_sec| is greater than all |boundary_end|, the - // function returns the largest |boundary_end|. Using the above |buckets| - // example, the function will return 30 if |timestamp_sec| = 30, and 290 if - // |timestamp_sec| = 299. - static int ExponentiallyBucketTimestamp(int timestamp_sec, - const Bucket* buckets, - size_t num_buckets); + // Bucketize |original_value| using given |buckets|, which is an array of + // Bucket and must be sorted in ascending order of |boundary_end|. + // |original_value| must be non-negative. An example of |buckets| is + // {{60, 1}, {300, 10}, {600, 20}}. This function looks for the first + // |boundary_end| > |original_value| and bucket it to the nearest |rounding|. + // If |original_value| is greater than all |boundary_end|, the function + // returns the largest |boundary_end|. Using the above |buckets| example, the + // function will return 30 if |original_value| = 30, and 290 if + // |original_value| = 299. + static int Bucketize(int original_value, + const Bucket* buckets, + size_t num_buckets); UserActivityLoggerDelegateUkm(); ~UserActivityLoggerDelegateUkm() override;
diff --git a/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm_unittest.cc index ef648b13..16de1276 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm_unittest.cc +++ b/chrome/browser/chromeos/power/ml/user_activity_logger_delegate_ukm_unittest.cc
@@ -51,12 +51,15 @@ features->set_last_activity_day(UserActivityEvent::Features::MON); features->set_last_activity_time_sec(7300); features->set_last_user_activity_time_sec(3800); + features->set_key_events_in_last_hour(20000); features->set_recent_time_active_sec(10); features->set_video_playing_time_sec(800); features->set_time_since_video_ended_sec(400); + features->set_mouse_events_in_last_hour(89); features->set_on_to_dim_sec(100); features->set_dim_to_screen_off_sec(200); features->set_time_since_last_mouse_sec(100); + features->set_touch_events_in_last_hour(1890); } void UpdateOpenTabsURLs() { @@ -141,8 +144,10 @@ {UserActivity::kDeviceModeName, UserActivityEvent::Features::CLAMSHELL}, {UserActivity::kDeviceTypeName, UserActivityEvent::Features::CHROMEBOOK}, {UserActivity::kLastActivityDayName, UserActivityEvent::Features::MON}, + {UserActivity::kKeyEventsInLastHourName, 10000}, {UserActivity::kLastActivityTimeName, 2}, {UserActivity::kLastUserActivityTimeName, 1}, + {UserActivity::kMouseEventsInLastHourName, 89}, {UserActivity::kOnBatteryName, base::nullopt}, {UserActivity::kRecentTimeActiveName, 10}, {UserActivity::kRecentVideoPlayingTimeName, 600}, @@ -151,7 +156,8 @@ {UserActivity::kSequenceIdName, 1}, {UserActivity::kTimeSinceLastKeyName, base::nullopt}, {UserActivity::kTimeSinceLastMouseName, 100}, - {UserActivity::kTimeSinceLastVideoEndedName, 360}}; + {UserActivity::kTimeSinceLastVideoEndedName, 360}, + {UserActivity::kTouchEventsInLastHourName, 1000}}; private: UserActivityLoggerDelegateUkm user_activity_logger_delegate_ukm_; @@ -160,15 +166,16 @@ TEST_F(UserActivityLoggerDelegateUkmTest, BucketEveryFivePercents) { const std::vector<int> original_values = {0, 14, 15, 100}; - const std::vector<int> buckets = {0, 10, 15, 100}; + const std::vector<int> results = {0, 10, 15, 100}; + constexpr UserActivityLoggerDelegateUkm::Bucket buckets[] = {{100, 5}}; + for (size_t i = 0; i < original_values.size(); ++i) { - EXPECT_EQ(buckets[i], - UserActivityLoggerDelegateUkm::BucketEveryFivePercents( - original_values[i])); + EXPECT_EQ(results[i], UserActivityLoggerDelegateUkm::Bucketize( + original_values[i], buckets, arraysize(buckets))); } } -TEST_F(UserActivityLoggerDelegateUkmTest, ExponentiallyBucketTimestamp) { +TEST_F(UserActivityLoggerDelegateUkmTest, Bucketize) { const std::vector<int> original_values = {0, 18, 59, 60, 62, 69, 72, 299, 300, 306, 316, 599, 600, 602}; constexpr UserActivityLoggerDelegateUkm::Bucket buckets[] = { @@ -176,9 +183,8 @@ const std::vector<int> results = {0, 18, 59, 60, 60, 60, 70, 290, 300, 300, 300, 580, 600, 600}; for (size_t i = 0; i < original_values.size(); ++i) { - EXPECT_EQ(results[i], - UserActivityLoggerDelegateUkm::ExponentiallyBucketTimestamp( - original_values[i], buckets, arraysize(buckets))); + EXPECT_EQ(results[i], UserActivityLoggerDelegateUkm::Bucketize( + original_values[i], buckets, arraysize(buckets))); } }
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.cc b/chrome/browser/conflicts/problematic_programs_updater_win.cc index a3db533b..80111026 100644 --- a/chrome/browser/conflicts/problematic_programs_updater_win.cc +++ b/chrome/browser/conflicts/problematic_programs_updater_win.cc
@@ -21,8 +21,8 @@ #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/browser_thread.h" -const base::Feature kIncompatibleSoftwareWarning{ - "IncompatibleSoftwareWarning", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kIncompatibleApplicationsWarning{ + "IncompatibleApplicationsWarning", base::FEATURE_DISABLED_BY_DEFAULT}; // ProblematicProgram ---------------------------------------------------------- @@ -59,7 +59,7 @@ std::unique_ptr<ProblematicProgramsUpdater> instance; - if (base::FeatureList::IsEnabled(kIncompatibleSoftwareWarning)) { + if (base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) { instance.reset( new ProblematicProgramsUpdater(module_list_filter, installed_programs)); } @@ -71,7 +71,7 @@ bool ProblematicProgramsUpdater::TrimCache() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (!base::FeatureList::IsEnabled(kIncompatibleSoftwareWarning)) + if (!base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) return false; std::vector<ProblematicProgram> programs = ConvertToProblematicProgramsVector( @@ -105,7 +105,7 @@ bool ProblematicProgramsUpdater::HasCachedPrograms() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (!base::FeatureList::IsEnabled(kIncompatibleSoftwareWarning)) + if (!base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) return false; return !g_browser_process->local_state() @@ -119,7 +119,7 @@ base::Value program_names(base::Value::Type::LIST); - if (!base::FeatureList::IsEnabled(kIncompatibleSoftwareWarning)) + if (!base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) return program_names; std::vector<ProblematicProgram> programs = ConvertToProblematicProgramsVector(
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.h b/chrome/browser/conflicts/problematic_programs_updater_win.h index e258c12..9d991c1 100644 --- a/chrome/browser/conflicts/problematic_programs_updater_win.h +++ b/chrome/browser/conflicts/problematic_programs_updater_win.h
@@ -19,8 +19,8 @@ class ModuleListFilter; class PrefRegistrySimple; -// A feature that controls whether Chrome warns about incompatible software. -extern const base::Feature kIncompatibleSoftwareWarning; +// A feature that controls whether Chrome warns about incompatible applications. +extern const base::Feature kIncompatibleApplicationsWarning; // Maintains a list of problematic programs that are installed on the machine. // These programs cause unwanted DLLs to be loaded into Chrome. @@ -29,7 +29,7 @@ // file so that it is available at startup, albeit somewhat out-of-date. To // remove stale elements from the list, use TrimCache(). // -// When kIncompatibleSoftwareWarning is disabled, this class always behaves +// When kIncompatibleApplicationsWarning is disabled, this class always behaves // as-if there are no problematic programs on the computer. This makes it safe // to use all of the class' static functions unconditionally. class ProblematicProgramsUpdater : public ModuleDatabaseObserver { @@ -39,7 +39,7 @@ static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); // Creates an instance of the updater. Returns nullptr if the - // kIncompatibleSoftwareWarning experiment is disabled. + // kIncompatibleApplicationsWarning experiment is disabled. // // |installed_programs| must outlive the lifetime of this class. static std::unique_ptr<ProblematicProgramsUpdater> MaybeCreate(
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc index 3a5d49c..eae7cff 100644 --- a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc +++ b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
@@ -96,7 +96,7 @@ void SetUp() override { ASSERT_NO_FATAL_FAILURE( registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER)); - scoped_feature_list_.InitAndEnableFeature(kIncompatibleSoftwareWarning); + scoped_feature_list_.InitAndEnableFeature(kIncompatibleApplicationsWarning); } enum class Option {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 8e66ee3..1fc552f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -388,6 +388,13 @@ "Experimental windowing and install banner treatment for Progressive Web " "Apps on desktop platforms. Implies #enable-experimental-app-banners."; +const char kEnableDesktopPWAsLinkCapturingName[] = + "Desktop PWAs Link Capturing"; +const char kEnableDesktopPWAsLinkCapturingDescription[] = + "Experimentally enable link capturing for Desktop PWAs. Navigations to " + "URLs that are in-scope of Desktop PWAs will open in a window. Requires " + "#enable-desktop-pwas."; + const char kEnableDockedMagnifierName[] = "Docked Magnifier"; const char kEnableDockedMagnifierDescription[] = "Enables the Docked Magnifier (a.k.a. picture-in-picture magnifier).";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b5471953..b00ad2e 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -269,6 +269,9 @@ extern const char kEnableDesktopPWAsName[]; extern const char kEnableDesktopPWAsDescription[]; +extern const char kEnableDesktopPWAsLinkCapturingName[]; +extern const char kEnableDesktopPWAsLinkCapturingDescription[]; + extern const char kEnableDockedMagnifierName[]; extern const char kEnableDockedMagnifierDescription[];
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc index 655f9650..67cdc65f 100644 --- a/chrome/browser/geolocation/geolocation_browsertest.cc +++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "base/time/clock.h" #include "build/build_config.h" @@ -24,6 +25,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/content_settings_usages_state.h" @@ -570,6 +572,13 @@ } IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, IFramesWithFreshPosition) { + // When permission delegation is enabled, there isn't a way to have a pending + // permission prompt when permission has already been granted in another frame + // on the same page. That means that this test isn't relevant and can be + // deleted after the feature is enabled by default. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kPermissionDelegation); + set_html_for_tests("/geolocation/two_iframes.html"); ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_DEFAULT)); LoadIFrames(); @@ -579,8 +588,8 @@ ASSERT_TRUE(WatchPositionAndGrantPermission()); ExpectPosition(fake_latitude(), fake_longitude()); - // In a second iframe from a different origin with a cached position the user - // is prompted. + // In a second iframe from a different origin with a cached position the + // user is prompted. SetFrameForScriptExecution("iframe_1"); WatchPositionAndObservePermissionRequest(true); @@ -592,8 +601,8 @@ fresh_position_longitude)); ExpectPosition(fresh_position_latitude, fresh_position_longitude); - // When permission is granted to the second iframe the fresh position gets to - // the script. + // When permission is granted to the second iframe the fresh position gets + // to the script. SetFrameForScriptExecution("iframe_1"); ASSERT_TRUE(WatchPositionAndGrantPermission()); ExpectPosition(fresh_position_latitude, fresh_position_longitude); @@ -624,6 +633,11 @@ } IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, CancelPermissionForFrame) { + // When permission delegation is removed, iframe requests are made for the top + // level frame. Navigating the iframe should not cancel the request. This + // test can be removed after the feature is enabled by default. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kPermissionDelegation); set_html_for_tests("/geolocation/two_iframes.html"); ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_DEFAULT)); LoadIFrames();
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc index 3c7392e..5315bd5 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -22,6 +22,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/test/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "base/time/clock.h" #include "chrome/browser/chrome_notification_types.h" @@ -33,6 +34,7 @@ #include "chrome/browser/permissions/permission_request_id.h" #include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" @@ -823,14 +825,17 @@ #endif TEST_F(GeolocationPermissionContextTests, QueuedPermission) { + // With permission delegation enabled, there can't be multiple permission + // requests on the same page. This test can be deleted once the feature is + // enabled by default. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kPermissionDelegation); GURL requesting_frame_0("https://www.example.com/geolocation"); GURL requesting_frame_1("https://www.example-2.com/geolocation"); - EXPECT_EQ( - CONTENT_SETTING_ASK, - GetGeolocationContentSetting(requesting_frame_0, requesting_frame_1)); - EXPECT_EQ( - CONTENT_SETTING_ASK, - GetGeolocationContentSetting(requesting_frame_1, requesting_frame_1)); + EXPECT_EQ(CONTENT_SETTING_ASK, GetGeolocationContentSetting( + requesting_frame_0, requesting_frame_1)); + EXPECT_EQ(CONTENT_SETTING_ASK, GetGeolocationContentSetting( + requesting_frame_1, requesting_frame_1)); NavigateAndCommit(requesting_frame_0); RequestManagerDocumentLoadCompleted(); @@ -839,10 +844,10 @@ EXPECT_FALSE(HasActivePrompt()); // Request permission for two frames. - RequestGeolocationPermission( - web_contents(), RequestID(0), requesting_frame_0, true); - RequestGeolocationPermission( - web_contents(), RequestID(1), requesting_frame_1, true); + RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame_0, + true); + RequestGeolocationPermission(web_contents(), RequestID(1), requesting_frame_1, + true); // Ensure only one prompt is created. ASSERT_TRUE(HasActivePrompt()); base::string16 text_0 = GetPromptText(); @@ -924,24 +929,17 @@ TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) { GURL frame_0("https://www.example.com/geolocation"); - GURL frame_1("https://www.example-2.com/geolocation"); EXPECT_EQ( CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_0, frame_0)); - EXPECT_EQ( - CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_1, frame_0)); NavigateAndCommit(frame_0); RequestManagerDocumentLoadCompleted(); ASSERT_FALSE(HasActivePrompt()); - // Request permission for two frames. RequestGeolocationPermission( web_contents(), RequestID(0), frame_0, true); - RequestGeolocationPermission( - web_contents(), RequestID(1), frame_1, true); - // Get the first permission request text. ASSERT_TRUE(HasActivePrompt()); base::string16 text_0 = GetPromptText(); ASSERT_FALSE(text_0.empty()); @@ -949,20 +947,9 @@ // Simulate the frame going away; the request should be removed. ClosePrompt(); - // Check that the next pending request is created correctly. - base::string16 text_1 = GetPromptText(); - EXPECT_NE(text_0, text_1); - - // Allow this frame and check that it worked. - AcceptPrompt(); - CheckTabContentsState(frame_1, CONTENT_SETTING_ALLOW); - CheckPermissionMessageSent(1, true); - - // Ensure the persisted permissions are ok. + // Ensure permission isn't persisted. EXPECT_EQ( CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_0, frame_0)); - EXPECT_EQ( - CONTENT_SETTING_ALLOW, GetGeolocationContentSetting(frame_1, frame_0)); } TEST_F(GeolocationPermissionContextTests, InvalidURL) { @@ -1013,6 +1000,11 @@ } TEST_F(GeolocationPermissionContextTests, QueuedOriginMultipleTabs) { + // With permission delegation enabled, there can't be multiple permission + // requests on the same page. This test can be deleted once the feature is + // enabled by default. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kPermissionDelegation); GURL url_a("https://www.example.com/geolocation"); GURL url_b("https://www.example-2.com/geolocation"); NavigateAndCommit(url_a); // Tab A0. @@ -1022,12 +1014,11 @@ // Request permission in both tabs; the extra tab will have two permission // requests from two origins. - RequestGeolocationPermission( - web_contents(), RequestID(0), url_a, true); - RequestGeolocationPermission( - extra_tabs_[0].get(), RequestIDForTab(0, 0), url_a, true); - RequestGeolocationPermission( - extra_tabs_[0].get(), RequestIDForTab(0, 1), url_b, true); + RequestGeolocationPermission(web_contents(), RequestID(0), url_a, true); + RequestGeolocationPermission(extra_tabs_[0].get(), RequestIDForTab(0, 0), + url_a, true); + RequestGeolocationPermission(extra_tabs_[0].get(), RequestIDForTab(0, 1), + url_b, true); ASSERT_TRUE(HasActivePrompt()); ASSERT_TRUE(HasActivePrompt(extra_tabs_[0].get())); @@ -1050,34 +1041,20 @@ } TEST_F(GeolocationPermissionContextTests, TabDestroyed) { - GURL requesting_frame_0("https://www.example.com/geolocation"); - GURL requesting_frame_1("https://www.example-2.com/geolocation"); - EXPECT_EQ( - CONTENT_SETTING_ASK, - GetGeolocationContentSetting(requesting_frame_0, requesting_frame_0)); - EXPECT_EQ( - CONTENT_SETTING_ASK, - GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0)); + GURL requesting_frame("https://www.example.com/geolocation"); + EXPECT_EQ(CONTENT_SETTING_ASK, + GetGeolocationContentSetting(requesting_frame, requesting_frame)); - NavigateAndCommit(requesting_frame_0); + NavigateAndCommit(requesting_frame); RequestManagerDocumentLoadCompleted(); // Request permission for two frames. - RequestGeolocationPermission( - web_contents(), RequestID(0), requesting_frame_0, false); - RequestGeolocationPermission( - web_contents(), RequestID(1), requesting_frame_1, false); + RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame, + false); - // Ensure only one prompt is created. ASSERT_TRUE(HasActivePrompt()); - - // The content settings should not have changed. - EXPECT_EQ( - CONTENT_SETTING_ASK, - GetGeolocationContentSetting(requesting_frame_0, requesting_frame_0)); - EXPECT_EQ( - CONTENT_SETTING_ASK, - GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0)); + EXPECT_EQ(CONTENT_SETTING_ASK, + GetGeolocationContentSetting(requesting_frame, requesting_frame)); } #if defined(OS_ANDROID)
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index fdfa65d..485fae6a 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -724,7 +724,6 @@ bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( net::URLRequest* request, - const base::FilePath& plugin_path, const std::string& mime_type, GURL* origin, std::string* payload) { @@ -748,31 +747,24 @@ !extension_info_map->IsIncognitoEnabled(extension_id))) { continue; } + + if (extension_id == extension_misc::kPdfExtensionId && + io_data->always_open_pdf_externally()->GetValue()) { + continue; + } + MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); if (!handler) continue; - // If a plugin path is provided then a stream is being intercepted for the - // mimeHandlerPrivate API. Otherwise a stream is being intercepted for the - // streamsPrivate API. - if (!plugin_path.empty()) { - if (handler->HasPlugin() && plugin_path == handler->GetPluginPath()) { - StreamTargetInfo target_info; - *origin = Extension::GetBaseURLFromExtensionId(extension_id); - target_info.extension_id = extension_id; - target_info.view_id = base::GenerateGUID(); - *payload = target_info.view_id; - stream_target_info_[request] = target_info; - return true; - } - } else { - if (!handler->HasPlugin() && handler->CanHandleMIMEType(mime_type)) { - StreamTargetInfo target_info; - *origin = Extension::GetBaseURLFromExtensionId(extension_id); - target_info.extension_id = extension_id; - stream_target_info_[request] = target_info; - return true; - } + if (handler->CanHandleMIMEType(mime_type)) { + StreamTargetInfo target_info; + *origin = Extension::GetBaseURLFromExtensionId(extension_id); + target_info.extension_id = extension_id; + target_info.view_id = base::GenerateGUID(); + *payload = target_info.view_id; + stream_target_info_[request] = target_info; + return true; } } #endif
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h index 3a49b51..d3add8f 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h
@@ -72,7 +72,6 @@ bool HandleExternalProtocol(const GURL& url, content::ResourceRequestInfo* info) override; bool ShouldInterceptResourceAsStream(net::URLRequest* request, - const base::FilePath& plugin_path, const std::string& mime_type, GURL* origin, std::string* payload) override;
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller.cc b/chrome/browser/media/webrtc/media_stream_devices_controller.cc index f5f6615..8eea57b 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller.cc
@@ -501,7 +501,7 @@ content_settings_->OnMediaStreamPermissionSet( PermissionManager::Get(profile_)->GetCanonicalOrigin( - request_.security_origin), + request_.security_origin, web_contents_->GetLastCommittedURL()), microphone_camera_state, selected_audio_device, selected_video_device, requested_audio_device, requested_video_device); }
diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc index bef84f0..389cced 100644 --- a/chrome/browser/permissions/permission_context_base.cc +++ b/chrome/browser/permissions/permission_context_base.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/db/database_manager.h" @@ -328,6 +329,17 @@ const BrowserPermissionCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // Under permission delegation, when we display a permission prompt, the + // origin displayed in the prompt should never differ from the top-level + // origin. The New Tab Page is excluded from this check as its effective + // requesting origin may be the Default Search Engine origin. Extensions are + // also excluded as currently they can request permission from iframes when + // embedded in non-secure contexts (https://crbug.com/530507). + DCHECK(!base::FeatureList::IsEnabled(features::kPermissionDelegation) || + embedding_origin == GURL(chrome::kChromeUINewTabURL).GetOrigin() || + requesting_origin.SchemeIs(extensions::kExtensionScheme) || + requesting_origin == embedding_origin); + PermissionRequestManager* permission_request_manager = PermissionRequestManager::FromWebContents(web_contents); // TODO(felt): sometimes |permission_request_manager| is null. This check is
diff --git a/chrome/browser/permissions/permission_delegation_browsertest.cc b/chrome/browser/permissions/permission_delegation_browsertest.cc new file mode 100644 index 0000000..5c40897 --- /dev/null +++ b/chrome/browser/permissions/permission_delegation_browsertest.cc
@@ -0,0 +1,147 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/permissions/permission_request_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_features.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "content/public/test/browser_test_utils.h" +#include "device/geolocation/public/cpp/scoped_geolocation_overrider.h" +#include "net/dns/mock_host_resolver.h" + +class PermissionDelegationBrowserTest : public InProcessBrowserTest { + public: + PermissionDelegationBrowserTest() + : geolocation_overrider_( + std::make_unique<device::ScopedGeolocationOverrider>(0, 0)) {} + ~PermissionDelegationBrowserTest() override = default; + + void SetUpOnMainThread() override { + scoped_feature_list_.InitAndEnableFeature(features::kPermissionDelegation); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(GetWebContents()); + mock_permission_prompt_factory_.reset( + new MockPermissionPromptFactory(manager)); + + https_embedded_test_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + https_embedded_test_server_->ServeFilesFromSourceDirectory( + "chrome/test/data"); + host_resolver()->AddRule("*", "127.0.0.1"); + content::SetupCrossSiteRedirector(https_embedded_test_server_.get()); + ASSERT_TRUE(https_embedded_test_server_->Start()); + } + + void TearDownOnMainThread() override { + mock_permission_prompt_factory_.reset(); + https_embedded_test_server_.reset(); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + // HTTPS server only serves a valid cert for localhost, so this is needed + // to load pages from other hosts without an error. + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + + MockPermissionPromptFactory* prompt_factory() { + return mock_permission_prompt_factory_.get(); + } + + content::WebContents* GetWebContents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + net::EmbeddedTestServer* https_embedded_test_server() { + return https_embedded_test_server_.get(); + } + + private: + std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; + std::unique_ptr<net::EmbeddedTestServer> https_embedded_test_server_; + std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_overrider_; + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(PermissionDelegationBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(PermissionDelegationBrowserTest, DelegatedToTwoFrames) { + prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL); + + // Main frame is on a.com, iframe 1 is on b.com and iframe 2 is on c.com. + GURL main_frame_url = + https_embedded_test_server()->GetURL("a.com", "/two_iframes_blank.html"); + GURL iframe_url_1 = + https_embedded_test_server()->GetURL("b.com", "/simple.html"); + GURL iframe_url_2 = + https_embedded_test_server()->GetURL("c.com", "/simple.html"); + + ui_test_utils::NavigateToURL(browser(), main_frame_url); + content::RenderFrameHost* main_frame = GetWebContents()->GetMainFrame(); + + // Delegate permission to both frames. + EXPECT_TRUE(content::ExecuteScript( + main_frame, + "document.getElementById('iframe1').allow = 'geolocation *';")); + EXPECT_TRUE(content::ExecuteScript( + main_frame, + "document.getElementById('iframe2').allow = 'geolocation *';")); + + // Load the iframes. + EXPECT_TRUE( + content::NavigateIframeToURL(GetWebContents(), "iframe1", iframe_url_1)); + EXPECT_TRUE( + content::NavigateIframeToURL(GetWebContents(), "iframe2", iframe_url_2)); + + content::RenderFrameHost* frame_1 = content::FrameMatchingPredicate( + GetWebContents(), + base::BindRepeating(&content::FrameMatchesName, "iframe1")); + EXPECT_NE(nullptr, frame_1); + content::RenderFrameHost* frame_2 = content::FrameMatchingPredicate( + GetWebContents(), + base::BindRepeating(&content::FrameMatchesName, "iframe2")); + EXPECT_NE(nullptr, frame_2); + + // Request permission from the first iframe. + bool result = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + frame_1, + "navigator.geolocation.getCurrentPosition(function(){ " + "domAutomationController.send(true); });", + &result)); + EXPECT_TRUE(result); + + // A prompt should have been shown with the top level origin rather than the + // iframe origin. + EXPECT_EQ(1, prompt_factory()->TotalRequestCount()); + EXPECT_TRUE(prompt_factory()->RequestOriginSeen(main_frame_url.GetOrigin())); + EXPECT_FALSE(prompt_factory()->RequestOriginSeen(iframe_url_1.GetOrigin())); + EXPECT_FALSE(prompt_factory()->RequestOriginSeen(iframe_url_2.GetOrigin())); + + // Request permission from the second iframe. Because it was granted to the + // top level frame, it should also be granted to this iframe and there should + // be no prompt. + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + frame_2, + "navigator.geolocation.getCurrentPosition(function(){ " + "domAutomationController.send(true); });", + &result)); + EXPECT_TRUE(result); + EXPECT_EQ(1, prompt_factory()->TotalRequestCount()); + + // Request permission from the top level frame. It should already be granted + // to this iframe and there should be no prompt. + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + main_frame, + "navigator.geolocation.getCurrentPosition(function(){ " + "domAutomationController.send(true); });", + &result)); + EXPECT_TRUE(result); + EXPECT_EQ(1, prompt_factory()->TotalRequestCount()); +}
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc index 76ddcb4..6f4b4ff 100644 --- a/chrome/browser/permissions/permission_manager.cc +++ b/chrome/browser/permissions/permission_manager.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/tab_contents/tab_util.h" #include "chrome/browser/vr/vr_tab_helper.h" #include "chrome/common/buildflags.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/browser_thread.h" @@ -40,6 +41,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "device/vr/features/features.h" +#include "extensions/common/constants.h" #include "ppapi/features/features.h" #if BUILDFLAG(ENABLE_PLUGINS) @@ -318,11 +320,44 @@ } } -GURL PermissionManager::GetCanonicalOrigin(const GURL& url) const { - if (url.GetOrigin() == GURL(chrome::kChromeSearchLocalNtpUrl).GetOrigin()) - return GURL(UIThreadSearchTermsData(profile_).GoogleBaseURLValue()); +GURL PermissionManager::GetCanonicalOrigin(const GURL& requesting_origin, + const GURL& embedding_origin) const { + if (requesting_origin.GetOrigin() == + GURL(chrome::kChromeSearchLocalNtpUrl).GetOrigin()) { + return GURL(UIThreadSearchTermsData(profile_).GoogleBaseURLValue()) + .GetOrigin(); + } - return url; + if (base::FeatureList::IsEnabled(features::kPermissionDelegation)) { + // TODO(raymes): There are caveats that need to be addressed before + // permission delegation is enabled by default: + // 1) It will cause permission reports from iframes to be recorded as if + // they are originating from the top-level frame. This is actually what we + // want when permission delegation is enabled because all prompts will be + // displayed on behalf of the top level origin and it should be the one + // penalized for delegating permission to badly behaving sites. Furthermore, + // when we migrate to UKM we will be unable to collect iframe URLs. + // 2) It will mean the permission blacklisting only applies to the top + // level origin. This may or may not be acceptable but regardless, + // permission blacklisting is not currently used and it's unclear whether it + // should be shipped or removed. + // 3) Once permission delegation is enabled by default, depending on the + // resolution of the above 2 points then it may be possible to remove + // "embedding_origin" as a parameter from all function calls in + // PermissionContextBase and subclasses. The embedding origin will always + // match the requesting origin. + + // Note that currently chrome extensions are allowed to use permissions even + // when in embedded in non-secure contexts. This is unfortunate and we + // should remove this at some point, but for now always use the requesting + // origin for embedded extensions. https://crbug.com/530507. + if (requesting_origin.SchemeIs(extensions::kExtensionScheme)) + return requesting_origin; + + return embedding_origin; + } + + return requesting_origin; } int PermissionManager::RequestPermission( @@ -364,7 +399,8 @@ #endif GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); - GURL canonical_requesting_origin = GetCanonicalOrigin(requesting_origin); + GURL canonical_requesting_origin = + GetCanonicalOrigin(requesting_origin, embedding_origin); int request_id = pending_requests_.Add(std::make_unique<PendingRequest>( render_frame_host, permissions, callback)); @@ -469,12 +505,13 @@ const GURL& requesting_origin, const GURL& embedding_origin) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - PermissionContextBase* context = - GetPermissionContext(PermissionTypeToContentSetting(permission)); + ContentSettingsType type = PermissionTypeToContentSetting(permission); + PermissionContextBase* context = GetPermissionContext(type); if (!context) return; - context->ResetPermission(GetCanonicalOrigin(requesting_origin).GetOrigin(), - embedding_origin.GetOrigin()); + context->ResetPermission( + GetCanonicalOrigin(requesting_origin, embedding_origin), + embedding_origin.GetOrigin()); } PermissionStatus PermissionManager::GetPermissionStatus( @@ -485,14 +522,14 @@ PermissionResult result = GetPermissionStatus(PermissionTypeToContentSetting(permission), requesting_origin, embedding_origin); - + ContentSettingsType type = PermissionTypeToContentSetting(permission); // TODO(benwells): split this into two functions, GetPermissionStatus and // GetPermissionStatusForPermissionsAPI. - PermissionContextBase* context = - GetPermissionContext(PermissionTypeToContentSetting(permission)); + PermissionContextBase* context = GetPermissionContext(type); if (context) { result = context->UpdatePermissionStatusWithDeviceStatus( - result, GetCanonicalOrigin(requesting_origin), embedding_origin); + result, GetCanonicalOrigin(requesting_origin, embedding_origin), + embedding_origin); } return ContentSettingToPermissionStatus(result.content_setting); @@ -510,7 +547,8 @@ ContentSettingsType content_type = PermissionTypeToContentSetting(permission); auto subscription = std::make_unique<Subscription>(); subscription->permission = content_type; - subscription->requesting_origin = GetCanonicalOrigin(requesting_origin); + subscription->requesting_origin = + GetCanonicalOrigin(requesting_origin, embedding_origin); subscription->embedding_origin = embedding_origin; subscription->callback = base::Bind(&SubscriptionCallbackWrapper, callback); @@ -582,7 +620,8 @@ content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, const GURL& embedding_origin) { - GURL canonical_requesting_origin = GetCanonicalOrigin(requesting_origin); + GURL canonical_requesting_origin = + GetCanonicalOrigin(requesting_origin, embedding_origin); PermissionContextBase* context = GetPermissionContext(permission); PermissionResult result = context->GetPermissionStatus( render_frame_host, canonical_requesting_origin.GetOrigin(),
diff --git a/chrome/browser/permissions/permission_manager.h b/chrome/browser/permissions/permission_manager.h index 72f47b9e..9e16887 100644 --- a/chrome/browser/permissions/permission_manager.h +++ b/chrome/browser/permissions/permission_manager.h
@@ -35,12 +35,17 @@ // Converts from |url|'s actual origin to the "canonical origin" that should // be used for the purpose of requesting/storing permissions. For example, the - // origin of the local NTP gets mapped to the Google base URL instead. All the - // public methods below, such as RequestPermission or GetPermissionStatus, - // take the actual origin and do the canonicalization internally. You only - // need to call this directly if you do something else with the origin, such - // as display it in the UI. - GURL GetCanonicalOrigin(const GURL& url) const; + // origin of the local NTP gets mapped to the Google base URL instead. With + // Permission Delegation it will transform the requesting origin into + // the embedding origin because all permission checks happen on the top level + // origin. + // + // All the public methods below, such as RequestPermission or + // GetPermissionStatus, take the actual origin and do the canonicalization + // internally. You only need to call this directly if you do something else + // with the origin, such as display it in the UI. + GURL GetCanonicalOrigin(const GURL& requesting_origin, + const GURL& embedding_origin) const; // Callers from within chrome/ should use the methods which take the // ContentSettingsType enum. The methods which take PermissionType values
diff --git a/chrome/browser/permissions/permission_manager_unittest.cc b/chrome/browser/permissions/permission_manager_unittest.cc index 7aeb50d..3e5d2b7 100644 --- a/chrome/browser/permissions/permission_manager_unittest.cc +++ b/chrome/browser/permissions/permission_manager_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/macros.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/permissions/permission_manager_factory.h" @@ -15,6 +16,7 @@ #include "chrome/browser/search_engines/ui_thread_search_terms_data.h" #include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h" #include "chrome/browser/vr/vr_tab_helper.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" @@ -497,7 +499,7 @@ EXPECT_EQ(PermissionStatusSource::UNSPECIFIED, result.source); } -TEST_F(PermissionManagerTest, GetCanonicalOrigin) { +TEST_F(PermissionManagerTest, GetCanonicalOriginSearch) { const GURL google_com("https://www.google.com"); const GURL google_de("https://www.google.de"); const GURL other_url("https://other.url"); @@ -508,17 +510,53 @@ const GURL other_chrome_search = GURL("chrome-search://not-local-ntp"); // "Normal" URLs are not affected by GetCanonicalOrigin. - EXPECT_EQ(google_com, GetPermissionManager()->GetCanonicalOrigin(google_com)); - EXPECT_EQ(google_de, GetPermissionManager()->GetCanonicalOrigin(google_de)); - EXPECT_EQ(other_url, GetPermissionManager()->GetCanonicalOrigin(other_url)); - EXPECT_EQ(google_base, - GetPermissionManager()->GetCanonicalOrigin(google_base)); + EXPECT_EQ(google_com, + GetPermissionManager()->GetCanonicalOrigin(google_com, google_com)); + EXPECT_EQ(google_de, + GetPermissionManager()->GetCanonicalOrigin(google_de, google_de)); + EXPECT_EQ(other_url, + GetPermissionManager()->GetCanonicalOrigin(other_url, other_url)); + EXPECT_EQ(google_base, GetPermissionManager()->GetCanonicalOrigin( + google_base, google_base)); // The local NTP URL gets mapped to the Google base URL. - EXPECT_EQ(google_base, GetPermissionManager()->GetCanonicalOrigin(local_ntp)); + EXPECT_EQ(google_base, + GetPermissionManager()->GetCanonicalOrigin(local_ntp, local_ntp)); // However, other chrome-search:// URLs, including the remote NTP URL, are // not affected. - EXPECT_EQ(remote_ntp, GetPermissionManager()->GetCanonicalOrigin(remote_ntp)); - EXPECT_EQ(other_chrome_search, - GetPermissionManager()->GetCanonicalOrigin(other_chrome_search)); + EXPECT_EQ(remote_ntp, + GetPermissionManager()->GetCanonicalOrigin(remote_ntp, remote_ntp)); + EXPECT_EQ(other_chrome_search, GetPermissionManager()->GetCanonicalOrigin( + other_chrome_search, other_chrome_search)); +} + +TEST_F(PermissionManagerTest, GetCanonicalOriginPermissionDelegation) { + const GURL requesting_origin("https://www.requesting.com"); + const GURL embedding_origin("https://www.google.de"); + const GURL extensions_requesting_origin( + "chrome-extension://abcdefghijklmnopqrstuvxyz"); + + { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kPermissionDelegation); + // Without permission delegation enabled the requesting origin should always + // be returned. + EXPECT_EQ(requesting_origin, GetPermissionManager()->GetCanonicalOrigin( + requesting_origin, embedding_origin)); + EXPECT_EQ(extensions_requesting_origin, + GetPermissionManager()->GetCanonicalOrigin( + extensions_requesting_origin, embedding_origin)); + } + + { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kPermissionDelegation); + // With permission delegation, the embedding origin should be returned + // except in the case of extensions. + EXPECT_EQ(embedding_origin, GetPermissionManager()->GetCanonicalOrigin( + requesting_origin, embedding_origin)); + EXPECT_EQ(extensions_requesting_origin, + GetPermissionManager()->GetCanonicalOrigin( + extensions_requesting_origin, embedding_origin)); + } }
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index 4f0428c4..6d567d6 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -16,10 +16,12 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" #include "components/printing/browser/print_composite_client.h" +#include "components/printing/browser/print_manager_utils.h" #include "components/printing/common/print_messages.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" +#include "content/public/common/content_switches.h" #include "content/public/test/browser_test_utils.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -207,6 +209,29 @@ } }; +class IsolateOriginsPrintBrowserTest : public PrintBrowserTest { + public: + static constexpr char kIsolatedSite[] = "b.com"; + + IsolateOriginsPrintBrowserTest() {} + ~IsolateOriginsPrintBrowserTest() override {} + + // content::BrowserTestBase + void SetUpCommandLine(base::CommandLine* command_line) override { + ASSERT_TRUE(embedded_test_server()->Start()); + + std::string origin_list = + embedded_test_server()->GetURL(kIsolatedSite, "/").spec(); + command_line->AppendSwitchASCII(switches::kIsolateOrigins, origin_list); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + } +}; + +constexpr char IsolateOriginsPrintBrowserTest::kIsolatedSite[]; + // Printing only a selection containing iframes is partially supported. // Iframes aren't currently displayed. This test passes whenever the print // preview is rendered (i.e. no timeout in the test). @@ -407,4 +432,53 @@ PrintAndWaitUntilPreviewIsReady(/*print_only_selection=*/false); } +// Printing preview a web page with an iframe from an isolated origin. +// This test passes whenever the print preview is rendered. This should not be +// a timed out test which indicates the print preview hung or crash. +IN_PROC_BROWSER_TEST_F(IsolateOriginsPrintBrowserTest, PrintIsolatedSubframe) { + ASSERT_TRUE(embedded_test_server()->Started()); + GURL url(embedded_test_server()->GetURL( + "/printing/content_with_same_site_iframe.html")); + GURL isolated_url( + embedded_test_server()->GetURL(kIsolatedSite, "/printing/test1.html")); + ui_test_utils::NavigateToURL(browser(), url); + + content::WebContents* original_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(NavigateIframeToURL(original_contents, "iframe", isolated_url)); + + ASSERT_EQ(2u, original_contents->GetAllFrames().size()); + auto* main_frame = original_contents->GetMainFrame(); + auto* subframe = original_contents->GetAllFrames()[1]; + ASSERT_NE(main_frame->GetProcess(), subframe->GetProcess()); + + PrintAndWaitUntilPreviewIsReady(/*print_only_selection=*/false); +} + +// Printing preview a webpage. +// Test that we won't use oopif printing by default, unless the +// test is run with site-per-process flag enabled. +IN_PROC_BROWSER_TEST_F(PrintBrowserTest, RegularPrinting) { + ASSERT_TRUE(embedded_test_server()->Started()); + GURL url(embedded_test_server()->GetURL("/printing/test1.html")); + ui_test_utils::NavigateToURL(browser(), url); + + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + EXPECT_TRUE(IsOopifEnabled()); + } else { + EXPECT_FALSE(IsOopifEnabled()); + } +} + +// Printing preview a webpage with isolate-origins enabled. +// Test that we will use oopif printing for this case. +IN_PROC_BROWSER_TEST_F(IsolateOriginsPrintBrowserTest, OopifPrinting) { + ASSERT_TRUE(embedded_test_server()->Started()); + GURL url(embedded_test_server()->GetURL("/printing/test1.html")); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_TRUE(IsOopifEnabled()); +} + } // namespace printing
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc index 550b0a8..fd885dec 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.cc +++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/net/chrome_url_request_context_getter.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "components/net_log/chrome_net_log.h" #include "components/prefs/pref_service.h" @@ -164,6 +165,12 @@ profile_->GetPrefs()); io_data_->safe_browsing_enabled()->MoveToThread( BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +#if BUILDFLAG(ENABLE_PLUGINS) + io_data_->always_open_pdf_externally()->Init( + prefs::kPluginsAlwaysOpenPdfExternally, profile_->GetPrefs()); + io_data_->always_open_pdf_externally()->MoveToThread( + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +#endif io_data_->InitializeOnUIThread(profile_); }
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 197db46..cb42c4e 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -344,6 +344,12 @@ pref_service); io_data_->safe_browsing_enabled()->MoveToThread( BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +#if BUILDFLAG(ENABLE_PLUGINS) + io_data_->always_open_pdf_externally()->Init( + prefs::kPluginsAlwaysOpenPdfExternally, pref_service); + io_data_->always_open_pdf_externally()->MoveToThread( + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +#endif io_data_->InitializeOnUIThread(profile_); }
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 2fab55b..2b85940 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1443,6 +1443,9 @@ if (chrome_http_user_agent_settings_) chrome_http_user_agent_settings_->CleanupOnUIThread(); incognito_availibility_pref_.Destroy(); +#if BUILDFLAG(ENABLE_PLUGINS) + always_open_pdf_externally_.Destroy(); +#endif #if defined(OS_CHROMEOS) account_consistency_mirror_required_pref_.Destroy(); #endif
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 7b22f86..1481cdf 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -36,6 +36,7 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_interceptor.h" #include "net/url_request/url_request_job_factory.h" +#include "ppapi/features/features.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/url_request_context_owner.h" @@ -211,6 +212,12 @@ return &incognito_availibility_pref_; } +#if BUILDFLAG(ENABLE_PLUGINS) + BooleanPrefMember* always_open_pdf_externally() const { + return &always_open_pdf_externally_; + } +#endif + #if defined(OS_CHROMEOS) BooleanPrefMember* account_consistency_mirror_required() const { return &account_consistency_mirror_required_pref_; @@ -580,6 +587,9 @@ mutable StringPrefMember allowed_domains_for_apps_; mutable IntegerPrefMember network_prediction_options_; mutable IntegerPrefMember incognito_availibility_pref_; +#if BUILDFLAG(ENABLE_PLUGINS) + mutable BooleanPrefMember always_open_pdf_externally_; +#endif #if defined(OS_CHROMEOS) mutable BooleanPrefMember account_consistency_mirror_required_pref_; #endif
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm index db37289a..7e6b0442 100644 --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm
@@ -97,10 +97,8 @@ ui_test_utils::NavigateToURL(browser(), url2_); ASSERT_EQ(url2_, GetWebContents()->GetURL()); - std::unique_ptr<base::SimpleTestTickClock> mock_clock( - new base::SimpleTestTickClock()); - mock_clock->Advance(base::TimeDelta::FromMilliseconds(100)); - ui::SetEventTickClockForTesting(std::move(mock_clock)); + mock_clock_.Advance(base::TimeDelta::FromMilliseconds(100)); + ui::SetEventTickClockForTesting(&mock_clock_); } void TearDownOnMainThread() override { event_queue_.reset(); } @@ -377,6 +375,8 @@ EXPECT_EQ(offset, scroll_offset); } + base::SimpleTestTickClock mock_clock_; + GURL url1_; GURL url2_; GURL url_iframe_;
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.cc b/chrome/browser/resource_coordinator/tab_activity_watcher.cc index 3a346058..53e9f635 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/tab_metrics_logger.h" +#include "chrome/browser/resource_coordinator/time.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" @@ -37,10 +38,53 @@ public: ~WebContentsData() override = default; - ukm::SourceId ukm_source_id() const { return ukm_source_id_; } + // Call when the associated WebContents has been replaced. + void WasReplaced() { was_replaced_ = true; } - const TabMetricsLogger::TabMetrics& tab_metrics() const { - return tab_metrics_; + // Call when the associated WebContents has replaced the WebContents of + // another tab. Copies info from the other WebContentsData so future events + // can be logged consistently. + void DidReplace(const WebContentsData& replaced_tab) { + // Copy background status so ForegroundOrClosed can potentially be logged. + backgrounded_time_ = replaced_tab.backgrounded_time_; + + // Copy the replaced tab's stats. + tab_metrics_.page_metrics = replaced_tab.tab_metrics_.page_metrics; + tab_metrics_.page_transition = replaced_tab.tab_metrics_.page_transition; + } + + // Call when the WebContents is detached from its tab. If the tab is later + // re-inserted elsewhere, we use the state it had before being detached. + void TabDetached() { is_detached_ = true; } + + // Call when the tab is inserted into a tab strip to update state. + void TabInserted(bool foreground) { + if (is_detached_) { + is_detached_ = false; + + // Dragged tabs are normally inserted into their new tab strip in the + // "background", then "activated", even though the user perceives the tab + // staying active the whole time. So don't update |background_time_| here. + // + // TODO(michaelpg): If a background tab is dragged (as part of a group) + // and inserted, it may be treated as being foregrounded (depending on tab + // order). This is a small edge case, but can be fixed by the plan to + // merge the ForegroundedOrClosed and TabMetrics events. + return; + } + + if (!foreground) { + // This is a new tab that was opened in the background. + backgrounded_time_ = NowTicks(); + } + } + + // Logs TabMetrics for the tab if it is considered to be backgrounded. + void LogTabIfBackgrounded() { + if (!backgrounded_time_.is_null()) { + TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogBackgroundTab( + ukm_source_id_, tab_metrics_); + } } private: @@ -56,6 +100,43 @@ ukm_source_id_ = ukm::GetSourceIdForWebContentsDocument(web_contents); } + void WasHidden() { + // The tab may not be in the tabstrip if it's being moved or replaced. + Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); + if (!browser) + return; + + DCHECK(!browser->tab_strip_model()->closing_all()); + + if (browser->tab_strip_model()->GetActiveWebContents() == web_contents() && + !browser->window()->IsMinimized()) { + // The active tab is considered to be in the foreground unless its window + // is minimized. It might still get hidden, e.g. when the browser is about + // to close, but that shouldn't count as a backgrounded event. + // + // TODO(michaelpg): On Mac, hiding the application (e.g. via Cmd+H) should + // log tabs as backgrounded. Check NSApplication's isHidden property. + return; + } + + backgrounded_time_ = NowTicks(); + LogTabIfBackgrounded(); + } + + void WasShown() { + if (backgrounded_time_.is_null()) + return; + + Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); + if (browser && browser->tab_strip_model()->closing_all()) + return; + + TabActivityWatcher::GetInstance() + ->tab_metrics_logger_->LogBackgroundTabShown( + ukm_source_id_, NowTicks() - backgrounded_time_); + backgrounded_time_ = base::TimeTicks(); + } + // content::WebContentsObserver: void RenderViewHostChanged(content::RenderViewHost* old_host, content::RenderViewHost* new_host) override { @@ -63,6 +144,7 @@ old_host->GetWidget()->RemoveInputEventObserver(this); new_host->GetWidget()->AddInputEventObserver(this); } + void DidFinishNavigation( content::NavigationHandle* navigation_handle) override { if (!navigation_handle->HasCommitted() || @@ -79,18 +161,25 @@ << "Expected a unique Source ID for the navigation"; ukm_source_id_ = new_source_id; + // Update navigation time for UKM reporting. + navigation_time_ = navigation_handle->NavigationStart(); + // Reset the per-page data. tab_metrics_.page_metrics = {}; // Update navigation info. tab_metrics_.page_transition = navigation_handle->GetPageTransition(); } + + // Logs metrics for the tab when it stops loading instead of immediately + // after a navigation commits, so we can have some idea of its status and + // contents. void DidStopLoading() override { - // Log metrics for the tab when it stops loading instead of immediately - // after a navigation commits, so we can have some idea of its status and - // contents. - TabActivityWatcher::GetInstance()->OnDidStopLoading(web_contents()); + // Ignore load events in foreground tabs. The tab state of a foreground tab + // will be logged if/when it is backgrounded. + LogTabIfBackgrounded(); } + void OnVisibilityChanged(content::Visibility visibility) override { // Ignore visibility changes while the WebContents is being destroyed. if (web_contents()->IsBeingDestroyed()) @@ -99,7 +188,23 @@ // TODO(michaelpg): Consider tracking occluded tabs, not just background // tabs. if (visibility == content::Visibility::HIDDEN) - TabActivityWatcher::GetInstance()->OnWasHidden(web_contents()); + WasHidden(); + else + WasShown(); + } + + void WebContentsDestroyed() override { + if (was_replaced_) + return; + + TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabLifetime( + ukm_source_id_, NowTicks() - navigation_time_); + + if (!backgrounded_time_.is_null()) { + TabActivityWatcher::GetInstance() + ->tab_metrics_logger_->LogBackgroundTabClosed( + ukm_source_id_, NowTicks() - backgrounded_time_); + } } // content::RenderWidgetHost::InputEventObserver: @@ -115,9 +220,22 @@ // Updated when a navigation is finished. ukm::SourceId ukm_source_id_ = 0; + // The most recent time the tab became backgrounded. This happens when a + // different tab in the tabstrip is activated or the tab's window is hidden. + base::TimeTicks backgrounded_time_; + + // The last navigation time associated with this tab. + base::TimeTicks navigation_time_; + // Stores current stats for the tab. TabMetricsLogger::TabMetrics tab_metrics_; + // Set to true when the WebContents has been detached from its tab. + bool is_detached_ = false; + + // If true, future events such as the tab being destroyed won't be logged. + bool was_replaced_ = false; + DISALLOW_COPY_AND_ASSIGN(WebContentsData); }; @@ -140,25 +258,34 @@ // Ensure the WebContentsData is created to observe this WebContents since it // may represent a newly created tab. WebContentsData::CreateForWebContents(contents); + WebContentsData::FromWebContents(contents)->TabInserted(foreground); +} + +void TabActivityWatcher::TabDetachedAt(content::WebContents* contents, + int index) { + WebContentsData::FromWebContents(contents)->TabDetached(); } void TabActivityWatcher::TabReplacedAt(TabStripModel* tab_strip_model, content::WebContents* old_contents, content::WebContents* new_contents, int index) { + WebContentsData* old_web_contents_data = + WebContentsData::FromWebContents(old_contents); + old_web_contents_data->WasReplaced(); + // Ensure the WebContentsData is created to observe this WebContents since it // likely hasn't been inserted into a tabstrip before. WebContentsData::CreateForWebContents(new_contents); + + WebContentsData::FromWebContents(new_contents) + ->DidReplace(*old_web_contents_data); } void TabActivityWatcher::TabPinnedStateChanged(TabStripModel* tab_strip_model, content::WebContents* contents, int index) { - // We only want UKMs for background tabs. - if (tab_strip_model->active_index() == index) - return; - - MaybeLogTab(contents); + WebContentsData::FromWebContents(contents)->LogTabIfBackgrounded(); } bool TabActivityWatcher::ShouldTrackBrowser(Browser* browser) { @@ -166,52 +293,6 @@ return !browser->profile()->IsOffTheRecord(); } -void TabActivityWatcher::OnWasHidden(content::WebContents* web_contents) { - DCHECK(web_contents); - - // The tab may not be in the tabstrip if it's being moved. - Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - if (!browser) - return; - - if (browser->tab_strip_model()->GetActiveWebContents() == web_contents && - !browser->window()->IsMinimized()) { - // The active tab is considered to be in the foreground unless its window is - // minimized. It might still get hidden, e.g. when the browser is about to - // close, but that shouldn't count as a backgrounded event. - // - // TODO(michaelpg): On Mac, hiding the application (e.g. via Cmd+H) should - // log tabs as backgrounded. Check NSApplication's isHidden property. - return; - } - - MaybeLogTab(web_contents); -} - -void TabActivityWatcher::OnDidStopLoading(content::WebContents* web_contents) { - // Ignore load events in foreground tabs. The tab state of a foreground tab - // will be logged if/when it is backgrounded. - if (web_contents->GetVisibility() != content::Visibility::HIDDEN) - return; - MaybeLogTab(web_contents); -} - -void TabActivityWatcher::MaybeLogTab(content::WebContents* web_contents) { - // Don't log when the WebContents is being closed or replaced. - if (web_contents->IsBeingDestroyed()) - return; - - DCHECK(!web_contents->GetBrowserContext()->IsOffTheRecord()); - - WebContentsData* web_contents_data = - WebContentsData::FromWebContents(web_contents); - DCHECK(web_contents_data); - - ukm::SourceId ukm_source_id = web_contents_data->ukm_source_id(); - tab_metrics_logger_->LogBackgroundTab(ukm_source_id, - web_contents_data->tab_metrics()); -} - void TabActivityWatcher::ResetForTesting() { tab_metrics_logger_ = std::make_unique<TabMetricsLogger>(); }
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.h b/chrome/browser/resource_coordinator/tab_activity_watcher.h index 83dc42d9..55834d0 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher.h +++ b/chrome/browser/resource_coordinator/tab_activity_watcher.h
@@ -40,6 +40,7 @@ content::WebContents* contents, int index, bool foreground) override; + void TabDetachedAt(content::WebContents* contents, int index) override; void TabReplacedAt(TabStripModel* tab_strip_model, content::WebContents* old_contents, content::WebContents* new_contents, @@ -47,18 +48,10 @@ void TabPinnedStateChanged(TabStripModel* tab_strip_model, content::WebContents* contents, int index) override; + // BrowserTabStripTrackerDelegate: bool ShouldTrackBrowser(Browser* browser) override; - // Called from WebContentsData when a tab is being hidden. - void OnWasHidden(content::WebContents* web_contents); - - // Called from WebContentsData when a tab has stopped loading. - void OnDidStopLoading(content::WebContents* web_contents); - - // Logs the tab with |web_contents|, unless it is being destroyed. - void MaybeLogTab(content::WebContents* web_contents); - // Resets internal state. void ResetForTesting();
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc index 6fe492c..0a0a104 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc
@@ -21,17 +21,15 @@ using metrics::TabMetricsEvent; using ukm::builders::TabManager_TabMetrics; +using ukm::builders::TabManager_Background_ForegroundedOrClosed; namespace resource_coordinator { namespace { const char* kEntryName = TabManager_TabMetrics::kEntryName; - -const GURL kTestUrls[] = { - GURL("https://example.com/"), GURL("https://google.fake"), - GURL("https://example3.com"), -}; +const char* kFOCEntryName = + TabManager_Background_ForegroundedOrClosed::kEntryName; // The default metric values for a tab. const UkmMetricMap kBasicMetricValues({ @@ -53,10 +51,14 @@ // metric. }); +// These parameters don't affect logging. +const bool kIsUserGesture = true; +const bool kCheckNavigationSuccess = true; + } // namespace // Tests UKM entries generated by TabActivityWatcher/TabMetricsLogger as tabs -// are backgrounded. +// are backgrounded and foregrounded. // Modeled after the TabActivityWatcherTest unit tests, these browser tests // focus on end-to-end testing from the first browser launch onwards, verifying // that window and browser commands are really triggering the paths that lead @@ -76,6 +78,11 @@ // Browser created in BrowserMain() shouldn't result in a background tab // being logged. EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kEntryName)); + + ASSERT_TRUE(embedded_test_server()->Start()); + test_urls_ = {embedded_test_server()->GetURL("/title1.html"), + embedded_test_server()->GetURL("/title2.html"), + embedded_test_server()->GetURL("/title3.html")}; } void TearDown() override { @@ -85,6 +92,21 @@ } protected: + void ExpectNewForegroundedEntry(const GURL& url) { + UkmMetricMap expected_metrics = { + {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1}, + }; + ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, url, expected_metrics); + } + + void ExpectNewClosedEntry(const GURL& url) { + UkmMetricMap expected_metrics = { + {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0}, + }; + ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, url, expected_metrics); + } + + std::vector<GURL> test_urls_; std::unique_ptr<UkmEntryChecker> ukm_entry_checker_; private: @@ -93,10 +115,9 @@ // Tests TabMetrics UKMs logged by creating and switching between tabs. IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, SwitchTabs) { - bool is_user_gesture = true; const GURL kTabUrls[] = { GURL(), // "about:blank" tab doesn't have a UKM source. - kTestUrls[0], kTestUrls[1], + test_urls_[0], test_urls_[1], }; EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kEntryName)); @@ -121,22 +142,29 @@ } // Switching to another tab logs the previously active tab. - browser()->tab_strip_model()->ActivateTabAt(0, is_user_gesture); + browser()->tab_strip_model()->ActivateTabAt(0, kIsUserGesture); { SCOPED_TRACE(""); ukm_entry_checker_->ExpectNewEntry(kEntryName, kTabUrls[2], expected_metrics); + ExpectNewForegroundedEntry(kTabUrls[0]); } - browser()->tab_strip_model()->ActivateTabAt(1, is_user_gesture); + browser()->tab_strip_model()->ActivateTabAt(1, kIsUserGesture); { SCOPED_TRACE(""); ukm_entry_checker_->ExpectNewEntry(kEntryName, kTabUrls[0], expected_metrics); + ExpectNewForegroundedEntry(kTabUrls[1]); } // Closing the window doesn't log more TabMetrics UKMs (tested in TearDown()). CloseBrowserSynchronously(browser()); + { + SCOPED_TRACE(""); + ExpectNewClosedEntry(kTabUrls[2]); + ExpectNewClosedEntry(kTabUrls[0]); + } } // Tests that switching between multiple windows doesn't affect TabMetrics UKMs. @@ -144,13 +172,11 @@ // what we log. If we needed to actually test different behavior based on window // focus, we would run these tests in interactive_ui_tests. IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, SwitchWindows) { - const bool check_navigation_success = false; - Browser* browser_2 = CreateBrowser(browser()->profile()); EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kEntryName)); - AddTabAtIndexToBrowser(browser(), 1, kTestUrls[0], ui::PAGE_TRANSITION_LINK, - check_navigation_success); + AddTabAtIndexToBrowser(browser(), 1, test_urls_[0], ui::PAGE_TRANSITION_LINK, + kCheckNavigationSuccess); { SCOPED_TRACE(""); UkmMetricMap expected_metrics = kBasicMetricValues; @@ -159,8 +185,8 @@ ukm_entry_checker_->ExpectNewEntry(kEntryName, GURL(), kBasicMetricValues); } - AddTabAtIndexToBrowser(browser_2, 1, kTestUrls[1], ui::PAGE_TRANSITION_LINK, - check_navigation_success); + AddTabAtIndexToBrowser(browser_2, 1, test_urls_[1], ui::PAGE_TRANSITION_LINK, + kCheckNavigationSuccess); { SCOPED_TRACE(""); UkmMetricMap expected_metrics = kBasicMetricValues; @@ -180,16 +206,12 @@ // Tests page with a beforeunload handler. IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, BeforeUnloadHandler) { - bool is_user_gesture = false; - - ASSERT_TRUE(embedded_test_server()->Start()); - // Navigate to a page with a beforeunload handler. GURL url(embedded_test_server()->GetURL("/beforeunload.html")); ui_test_utils::NavigateToURL(browser(), url); // Log metrics for the first tab by switching to a new tab. - AddTabAtIndex(1, kTestUrls[0], ui::PAGE_TRANSITION_LINK); + AddTabAtIndex(1, test_urls_[0], ui::PAGE_TRANSITION_LINK); UkmMetricMap expected_metrics = kBasicMetricValues; expected_metrics[TabManager_TabMetrics::kHasBeforeUnloadHandlerName] = 1; expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2; @@ -199,12 +221,69 @@ } // Sanity check: the new tab doesn't have a beforeunload handler. - browser()->tab_strip_model()->ActivateTabAt(0, is_user_gesture); + browser()->tab_strip_model()->ActivateTabAt(0, kIsUserGesture); { SCOPED_TRACE(""); - ukm_entry_checker_->ExpectNewEntry(kEntryName, kTestUrls[0], + ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[0], kBasicMetricValues); } } +// Tests events logged when dragging a tab between browsers. +IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, TabDrag) { + // This test will navigate 3 tabs. + const GURL kBrowserStartUrl = test_urls_[0]; + const GURL kBrowser2StartUrl = test_urls_[1]; + const GURL kDraggedTabUrl = test_urls_[2]; + + Browser* browser_2 = CreateBrowser(browser()->profile()); + + ui_test_utils::NavigateToURL(browser(), kBrowserStartUrl); + ui_test_utils::NavigateToURL(browser_2, kBrowser2StartUrl); + + // Adding a tab backgrounds the original tab in the window. + AddTabAtIndexToBrowser(browser(), 1, kDraggedTabUrl, ui::PAGE_TRANSITION_LINK, + kCheckNavigationSuccess); + { + SCOPED_TRACE(""); + ukm_entry_checker_->ExpectNewEntry( + kEntryName, kBrowserStartUrl, + {{TabManager_TabMetrics::kWindowIdName, browser()->session_id().id()}}); + } + + // "Drag" the new tab out of its browser. + content::WebContents* dragged_contents = + browser()->tab_strip_model()->GetWebContentsAt(1); + browser()->tab_strip_model()->DetachWebContentsAt(1); + dragged_contents->WasHidden(); + // The other tab in the browser is now foregrounded. + ExpectNewForegroundedEntry(kBrowserStartUrl); + + // "Drop" the tab into the other browser. This requires showing and + // reactivating the tab, but to the user, it never leaves the foreground, so + // we don't log a foregrounded event for it. + browser_2->tab_strip_model()->InsertWebContentsAt(1, dragged_contents, + TabStripModel::ADD_NONE); + dragged_contents->WasShown(); + browser_2->tab_strip_model()->ActivateTabAt(1, kIsUserGesture); + EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kFOCEntryName)); + + // The first tab in this window was backgrounded when the new one was + // inserted. + { + SCOPED_TRACE(""); + ukm_entry_checker_->ExpectNewEntry( + kEntryName, kBrowser2StartUrl, + {{TabManager_TabMetrics::kWindowIdName, browser_2->session_id().id()}}); + } + + // Closing the window with 2 tabs means we log the backgrounded tab as closed. + CloseBrowserSynchronously(browser_2); + ExpectNewClosedEntry(kBrowser2StartUrl); + + CloseBrowserSynchronously(browser()); + EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kEntryName)); + EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kFOCEntryName)); +} + } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc index c966f93e..c4779fc 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
@@ -34,12 +34,12 @@ using content::WebContentsTester; using metrics::TabMetricsEvent; using ukm::builders::TabManager_TabMetrics; +using ForegroundedOrClosed = + ukm::builders::TabManager_Background_ForegroundedOrClosed; namespace resource_coordinator { namespace { -const char* kEntryName = TabManager_TabMetrics::kEntryName; - const GURL kTestUrls[] = { GURL("https://example.com/"), GURL("https://google.fake"), GURL("https://example3.com"), @@ -68,19 +68,38 @@ } // namespace -// Tests UKM entries generated by TabMetricsLogger at the request of -// TabActivityWatcher. +// Base class for testing tab UKM (URL-Keyed Metrics) entries logged by +// TabMetricsLogger via TabActivityWatcher. class TabActivityWatcherTest : public ChromeRenderViewHostTestHarness { - protected: + public: TabActivityWatcherTest() { TabActivityWatcher::GetInstance()->ResetForTesting(); } + ~TabActivityWatcherTest() override = default; + void TearDown() override { TabActivityWatcher::GetInstance()->ResetForTesting(); ChromeRenderViewHostTestHarness::TearDown(); } + protected: + UkmEntryChecker ukm_entry_checker_; + TabActivitySimulator tab_activity_simulator_; + + private: + DISALLOW_COPY_AND_ASSIGN(TabActivityWatcherTest); +}; + +// Tests TabManager.TabMetrics UKM entries generated when tabs are backgrounded. +class TabMetricsTest : public TabActivityWatcherTest { + public: + TabMetricsTest() = default; + ~TabMetricsTest() override = default; + + protected: + // Expects that a new TabMetrics event has been logged for |source_url| + // with the expected metrics and the next available SequenceId. void ExpectNewEntry(const GURL& source_url, const UkmMetricMap& expected_metrics) { ukm_entry_checker_.ExpectNewEntry(kEntryName, source_url, expected_metrics); @@ -93,14 +112,13 @@ } protected: - UkmEntryChecker ukm_entry_checker_; - TabActivitySimulator tab_activity_simulator_; + const char* kEntryName = TabManager_TabMetrics::kEntryName; private: - DISALLOW_COPY_AND_ASSIGN(TabActivityWatcherTest); + DISALLOW_COPY_AND_ASSIGN(TabMetricsTest); }; -TEST_F(TabActivityWatcherTest, Basic) { +TEST_F(TabMetricsTest, Basic) { Browser::CreateParams params(profile(), true); std::unique_ptr<Browser> browser = CreateBrowserWithTestWindowForParams(¶ms); @@ -143,7 +161,7 @@ } // Tests when tab events like pinning and navigating trigger logging. -TEST_F(TabActivityWatcherTest, TabEvents) { +TEST_F(TabMetricsTest, TabEvents) { Browser::CreateParams params(profile(), true); std::unique_ptr<Browser> browser = CreateBrowserWithTestWindowForParams(¶ms); @@ -203,7 +221,7 @@ } // Tests setting and changing tab metrics. -TEST_F(TabActivityWatcherTest, TabMetrics) { +TEST_F(TabMetricsTest, TabMetrics) { Browser::CreateParams params(profile(), true); std::unique_ptr<Browser> browser = CreateBrowserWithTestWindowForParams(¶ms); @@ -275,7 +293,7 @@ // Tests counting input events. TODO(michaelpg): Currently only tests mouse // events. -TEST_F(TabActivityWatcherTest, InputEvents) { +TEST_F(TabMetricsTest, InputEvents) { Browser::CreateParams params(profile(), true); std::unique_ptr<Browser> browser = CreateBrowserWithTestWindowForParams(¶ms); @@ -352,7 +370,7 @@ // Tests that logging doesn't occur when the WebContents is hidden while still // the active tab, e.g. when the browser window hides before closing. -TEST_F(TabActivityWatcherTest, HideWebContents) { +TEST_F(TabMetricsTest, HideWebContents) { Browser::CreateParams params(profile(), true); std::unique_ptr<Browser> browser = CreateBrowserWithTestWindowForParams(¶ms); @@ -376,7 +394,7 @@ } // Tests navigation-related metrics. -TEST_F(TabActivityWatcherTest, Navigations) { +TEST_F(TabMetricsTest, Navigations) { Browser::CreateParams params(profile(), true); auto browser = CreateBrowserWithTestWindowForParams(¶ms); TabStripModel* tab_strip_model = browser->tab_strip_model(); @@ -501,7 +519,7 @@ // Tests that replacing a foreground tab doesn't log new tab metrics until the // new tab is backgrounded. -TEST_F(TabActivityWatcherTest, ReplaceForegroundTab) { +TEST_F(TabMetricsTest, ReplaceForegroundTab) { Browser::CreateParams params(profile(), true); std::unique_ptr<Browser> browser = CreateBrowserWithTestWindowForParams(¶ms); @@ -545,4 +563,92 @@ tab_strip_model->CloseAllTabs(); } +// Tests TabManager.Background.ForegroundedOrClosed UKMs logged by +// TabActivityWatcher. +class ForegroundedOrClosedTest : public TabActivityWatcherTest { + public: + ForegroundedOrClosedTest() = default; + ~ForegroundedOrClosedTest() override = default; + + protected: + const char* kEntryName = ForegroundedOrClosed::kEntryName; + + private: + DISALLOW_COPY_AND_ASSIGN(ForegroundedOrClosedTest); +}; + +// Tests TabManager.Backgrounded.ForegroundedOrClosed UKM logging. +TEST_F(ForegroundedOrClosedTest, SingleTab) { + Browser::CreateParams params(profile(), true); + std::unique_ptr<Browser> browser = + CreateBrowserWithTestWindowForParams(¶ms); + + TabStripModel* tab_strip_model = browser->tab_strip_model(); + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model, + GURL(kTestUrls[0])); + + // The tab is in the foreground, so it isn't logged as a background tab. + tab_strip_model->CloseWebContentsAt(0, TabStripModel::CLOSE_USER_GESTURE); + EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName)); +} + +// Tests TabManager.Backgrounded.ForegroundedOrClosed UKM logging. +TEST_F(ForegroundedOrClosedTest, MultipleTabs) { + Browser::CreateParams params(profile(), true); + std::unique_ptr<Browser> browser = + CreateBrowserWithTestWindowForParams(¶ms); + + TabStripModel* tab_strip_model = browser->tab_strip_model(); + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model, + GURL(kTestUrls[0])); + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model, + GURL(kTestUrls[1])); + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model, + GURL(kTestUrls[2])); + + // Foreground a tab to log an event. + tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 2); + { + SCOPED_TRACE(""); + ukm_entry_checker_.ExpectNewEntry( + kEntryName, kTestUrls[2], + { + {ForegroundedOrClosed::kIsForegroundedName, 1}, + }); + } + + // Foreground the middle tab to log another event. + tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1); + { + SCOPED_TRACE(""); + ukm_entry_checker_.ExpectNewEntry( + kEntryName, kTestUrls[1], + { + {ForegroundedOrClosed::kIsForegroundedName, 1}, + }); + } + + // Close all tabs. Background tabs are logged as closed. + tab_strip_model->CloseAllTabs(); + { + SCOPED_TRACE(""); + // The rightmost tab was in the background and was closed. + ukm_entry_checker_.ExpectNewEntry( + kEntryName, kTestUrls[2], + { + {ForegroundedOrClosed::kIsForegroundedName, 0}, + }); + + // The leftmost tab was in the background and was closed. + ukm_entry_checker_.ExpectNewEntry( + kEntryName, kTestUrls[0], + { + {ForegroundedOrClosed::kIsForegroundedName, 0}, + }); + + // No event is logged for the middle tab, which was in the foreground. + EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName)); + } +} + } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc index f7055cb..059cfc86 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc
@@ -14,8 +14,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" -#include "services/metrics/public/cpp/ukm_builders.h" -#include "services/metrics/public/cpp/ukm_recorder.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" using base::TimeTicks; @@ -29,8 +27,7 @@ TabManager::WebContentsData::WebContentsData(content::WebContents* web_contents) : WebContentsObserver(web_contents), time_to_purge_(base::TimeDelta::FromMinutes(30)), - is_purged_(false), - ukm_source_id_(0) { + is_purged_(false) { tab_data_.is_hidden = web_contents->GetVisibility() == content::Visibility::HIDDEN; } @@ -69,26 +66,6 @@ content::NavigationHandle* navigation_handle) { SetIsInSessionRestore(false); g_browser_process->GetTabManager()->OnDidFinishNavigation(navigation_handle); - - if (!navigation_handle->HasCommitted() || navigation_handle->IsErrorPage() || - navigation_handle->IsSameDocument() || - !navigation_handle->IsInMainFrame()) { - return; - } - - tab_data_.navigation_time = navigation_handle->NavigationStart(); - ukm_source_id_ = ukm::ConvertToSourceId(navigation_handle->GetNavigationId(), - ukm::SourceIdType::NAVIGATION_ID); -} - -void TabManager::WebContentsData::OnVisibilityChanged( - content::Visibility visibility) { - bool was_hidden = tab_data_.is_hidden; - tab_data_.is_hidden = visibility == content::Visibility::HIDDEN; - if (!tab_data_.is_hidden && was_hidden && - !tab_data_.last_inactive_time.is_null()) { - ReportUKMWhenBackgroundTabIsClosedOrForegrounded(true); - } } void TabManager::WebContentsData::WebContentsDestroyed() { @@ -107,13 +84,6 @@ base::TimeDelta::FromDays(1), 100); } - ReportUKMWhenTabIsClosed(); - - if (web_contents()->GetVisibility() == content::Visibility::HIDDEN && - !tab_data_.last_inactive_time.is_null()) { - ReportUKMWhenBackgroundTabIsClosedOrForegrounded(false); - } - SetTabLoadingState(TAB_IS_NOT_LOADING); SetIsInSessionRestore(false); g_browser_process->GetTabManager()->OnWebContentsDestroyed(web_contents()); @@ -194,26 +164,6 @@ } } -void TabManager::WebContentsData::ReportUKMWhenTabIsClosed() { - if (!ukm_source_id_) - return; - auto duration = NowTicks() - tab_data_.navigation_time; - ukm::builders::TabManager_TabLifetime(ukm_source_id_) - .SetTimeSinceNavigation(duration.InMilliseconds()) - .Record(ukm::UkmRecorder::Get()); -} - -void TabManager::WebContentsData:: - ReportUKMWhenBackgroundTabIsClosedOrForegrounded(bool is_foregrounded) { - if (!ukm_source_id_) - return; - auto duration = NowTicks() - tab_data_.last_inactive_time; - ukm::builders::TabManager_Background_ForegroundedOrClosed(ukm_source_id_) - .SetTimeFromBackgrounded(duration.InMilliseconds()) - .SetIsForegrounded(is_foregrounded) - .Record(ukm::UkmRecorder::Get()); -} - TabManager::WebContentsData::Data::Data() : id(0), is_discarded(false),
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h index 20f96dc..d200715 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h
@@ -11,7 +11,6 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -#include "services/metrics/public/cpp/ukm_source_id.h" namespace content { class WebContents; @@ -58,7 +57,6 @@ content::NavigationHandle* navigation_handle) override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; - void OnVisibilityChanged(content::Visibility visibility) override; void WebContentsDestroyed() override; // Called by TabManager::ResourceCoordinatorSignalObserver to notify that a @@ -172,9 +170,6 @@ bool is_hidden; // Is the tab playing audio? bool is_recently_audible; - // The navigation time associated with this tab. Useful as a reference time - // from which to measure UKM event timings. - base::TimeTicks navigation_time; // Last time the tab started or stopped playing audio (we record the // transition time). base::TimeTicks last_audio_change_time; @@ -195,9 +190,6 @@ bool is_restored_in_foreground; }; - void ReportUKMWhenTabIsClosed(); - void ReportUKMWhenBackgroundTabIsClosedOrForegrounded(bool is_foregrounded); - // Contains all the needed data for the tab. Data tab_data_; @@ -207,8 +199,6 @@ // True if the tab has been purged. bool is_purged_; - ukm::SourceId ukm_source_id_; - DISALLOW_COPY_AND_ASSIGN(WebContentsData); };
diff --git a/chrome/browser/resource_coordinator/tab_metrics_logger.cc b/chrome/browser/resource_coordinator/tab_metrics_logger.cc index 85734fe5..c9033e0 100644 --- a/chrome/browser/resource_coordinator/tab_metrics_logger.cc +++ b/chrome/browser/resource_coordinator/tab_metrics_logger.cc
@@ -110,6 +110,19 @@ ui::PageTransitionIsRedirect(page_transition)); } +// Logs the TabManager.Background.ForegroundedOrClosed event. +void LogBackgroundTabForegroundedOrClosed(ukm::SourceId ukm_source_id, + base::TimeDelta inactive_duration, + bool is_foregrounded) { + if (!ukm_source_id) + return; + + ukm::builders::TabManager_Background_ForegroundedOrClosed(ukm_source_id) + .SetTimeFromBackgrounded(inactive_duration.InMilliseconds()) + .SetIsForegrounded(is_foregrounded) + .Record(ukm::UkmRecorder::Get()); +} + } // namespace TabMetricsLogger::TabMetricsLogger() = default; @@ -172,10 +185,6 @@ if (!ukm_source_id) return; - ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); - if (!ukm_recorder) - return; - content::WebContents* web_contents = tab_metrics.web_contents; // UKM recording is disabled in OTR. @@ -240,5 +249,28 @@ .SetIsPinned(tab_strip_model->IsTabPinned(index)) .SetNavigationEntryCount(web_contents->GetController().GetEntryCount()) .SetSequenceId(++sequence_id_) - .Record(ukm_recorder); + .Record(ukm::UkmRecorder::Get()); +} + +void TabMetricsLogger::LogBackgroundTabShown( + ukm::SourceId ukm_source_id, + base::TimeDelta inactive_duration) { + LogBackgroundTabForegroundedOrClosed(ukm_source_id, inactive_duration, + true /* is_shown */); +} + +void TabMetricsLogger::LogBackgroundTabClosed( + ukm::SourceId ukm_source_id, + base::TimeDelta inactive_duration) { + LogBackgroundTabForegroundedOrClosed(ukm_source_id, inactive_duration, + false /* is_shown */); +} + +void TabMetricsLogger::LogTabLifetime(ukm::SourceId ukm_source_id, + base::TimeDelta time_since_navigation) { + if (!ukm_source_id) + return; + ukm::builders::TabManager_TabLifetime(ukm_source_id) + .SetTimeSinceNavigation(time_since_navigation.InMilliseconds()) + .Record(ukm::UkmRecorder::Get()); }
diff --git a/chrome/browser/resource_coordinator/tab_metrics_logger.h b/chrome/browser/resource_coordinator/tab_metrics_logger.h index 11d5715..07105dc 100644 --- a/chrome/browser/resource_coordinator/tab_metrics_logger.h +++ b/chrome/browser/resource_coordinator/tab_metrics_logger.h
@@ -10,9 +10,13 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "ui/base/page_transition_types.h" +namespace base { +class TimeDelta; +} // namespace base + namespace content { class WebContents; -} +} // namespace content // Logs metrics for a tab and its WebContents when requested. // Must be used on the UI thread. @@ -49,6 +53,20 @@ void LogBackgroundTab(ukm::SourceId ukm_source_id, const TabMetrics& tab_metrics); + // Logs TabManager.Background.ForegroundedOrClosed UKM for a tab that was + // shown after being inactive. + void LogBackgroundTabShown(ukm::SourceId ukm_source_id, + base::TimeDelta inactive_duration); + + // Logs TabManager.Background.ForegroundedOrClosed UKM for a tab that was + // closed after being inactive. + void LogBackgroundTabClosed(ukm::SourceId ukm_source_id, + base::TimeDelta inactive_duration); + + // Logs TabManager.TabLifetime UKM for a closed tab. + void LogTabLifetime(ukm::SourceId ukm_source_id, + base::TimeDelta time_since_navigation); + // Returns the ContentType that matches |mime_type|. static metrics::TabMetricsEvent::ContentType GetContentTypeFromMimeType( const std::string& mime_type);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js index fdff824e..53ae906 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js
@@ -479,6 +479,15 @@ case 'forceClickOnCurrentItem': if (ChromeVoxState.instance.currentRange) { var actionNode = ChromeVoxState.instance.currentRange.start.node; + // Scan for a clickable, which overrides the |actionNode|. + var clickable = actionNode; + while (clickable && !clickable.clickable) + clickable = clickable.parent; + if (clickable) { + clickable.doDefault(); + return false; + } + while (actionNode.role == RoleType.INLINE_TEXT_BOX || actionNode.role == RoleType.STATIC_TEXT) actionNode = actionNode.parent; @@ -486,11 +495,7 @@ ChromeVoxState.instance.navigateToRange( cursors.Range.fromNode(actionNode.inPageLinkTarget)); } else { - // Scan for a clickable, which overrides the |actionNode|. - var clickable = actionNode; - while (clickable && !clickable.clickable) - clickable = clickable.parent; - clickable ? clickable.doDefault() : actionNode.doDefault(); + actionNode.doDefault(); } } // Skip all other processing; if focus changes, we should get an event
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js index eefb211..69f23733 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -420,7 +420,7 @@ speak: `$name $role @describe_index($posInSet, $setSize) $state $restriction $description` }, - paragraph: {speak: `$descendants`}, + paragraph: {speak: `$nameOrDescendants`}, popUpButton: { speak: `$if($value, $value, $descendants) $name $role @aria_has_popup $state $restriction $description` @@ -630,6 +630,10 @@ return node.htmlAttributes['aria-posinset']; case 'setSize': return node.htmlAttributes['aria-setsize']; + + // These attributes default to false for empty strings. + case 'roleDescription': + return !!node.roleDescription; default: return node[attrib] !== undefined || node.state[attrib]; } @@ -1035,8 +1039,10 @@ options.annotation.push(new Output.SelectionSpan( node.textSelStart || 0, node.textSelEnd || 0)); - selectedText = node.value.substring( - node.textSelStart || 0, node.textSelEnd || 0); + if (node.value) { + selectedText = node.value.substring( + node.textSelStart || 0, node.textSelEnd || 0); + } } options.annotation.push(token); if (selectedText && !this.formatOptions_.braille) {
diff --git a/chrome/browser/resources/chromeos/genius_app/manifest.json b/chrome/browser/resources/chromeos/genius_app/manifest.json index 6a625f7..e0f1b72 100644 --- a/chrome/browser/resources/chromeos/genius_app/manifest.json +++ b/chrome/browser/resources/chromeos/genius_app/manifest.json
@@ -46,6 +46,7 @@ "https://www.googleapis.com/auth/supportcontent", "https://www.googleapis.com/auth/cases", "https://www.googleapis.com/auth/cases.readonly", + "https://www.googleapis.com/auth/pixelbook.email.preferences", "https://www.google.com/accounts/OAuthLogin" ] },
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js index 1b05611..fd88e5e8 100644 --- a/chrome/browser/resources/chromeos/login/oobe.js +++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -227,15 +227,7 @@ * @param {text} password TPM password to be shown. */ setTpmPassword: function(password) { - $('tpm-busy').hidden = true; - - if (password.length) { - $('tpm-password').textContent = password; - $('tpm-password').hidden = false; - } else { - $('tpm-desc').hidden = true; - $('tpm-desc-powerwash').hidden = false; - } + $('eula').setTpmPassword(password); }, /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.css b/chrome/browser/resources/chromeos/login/oobe_eula.css index b2728a7..fe80252f 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.css +++ b/chrome/browser/resources/chromeos/login/oobe_eula.css
@@ -55,6 +55,21 @@ padding: 0 6px; /* = 8px - 2px back button border */ } -#eula-accept-button { +#eula-accept-button, +#settings-close-button { -webkit-padding-end: 18px; } + +.tpm-password > div { + margin-top: 18px; +} + +.password-row div { + color: rgb(66, 133, 244); + font: 24px Roboto; + margin-top: 82px; +} + +.installation-settings-spinner { + -webkit-margin-end: 5px; +}
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.html b/chrome/browser/resources/chromeos/login/oobe_eula.html index 6fe171c..48fc992 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.html +++ b/chrome/browser/resources/chromeos/login/oobe_eula.html
@@ -39,6 +39,7 @@ <dom-module id="oobe-eula-md"> <template> + <link rel="stylesheet" href="chrome://resources/css/throbber.css"> <link rel="stylesheet" href="oobe_eula.css"> <link rel="stylesheet" href="oobe_dialog_parameters.css"> <link rel="stylesheet" href="oobe_flex_layout.css"> @@ -94,5 +95,40 @@ </oobe-text-button> </div> </oobe-dialog> + <oobe-dialog id="installationSettingsDialog" role="dialog" + has-buttons hidden> + <hd-iron-icon class="oobe-icon" + icon1x="oobe-eula-32:googleg" icon2x="oobe-eula-64:googleg"> + </hd-iron-icon> + <div class="header"> + <h1 class="title" i18n-content="eulaSystemInstallationSettings"></h1> + <div class="subtitle"> + <div i18n-content="eulaTpmDesc"></div> + <div class='tpm-password'> + <div hidden="[[isPasswordEmpty_(password)]]" + i18n-content="eulaTpmKeyDesc"></div> + <div hidden="[[!isPasswordEmpty_(password)]]" + i18n-content="eulaTpmDescPowerwash"></div> + <div class="layout horizontal" + hidden="[[!isWaitingForPassword_(password)]]"> + <div class="installation-settings-spinner throbber"></div> + <div i18n-content="eulaTpmBusy"></div> + </div> + <div class='password-row layout horizontal'> + <div class="flex"></div> + <div>{{password}}</div> + <div class="flex"></div> + </div> + </div> + </div> + </div> + <div class="bottom-buttons flex layout horizontal"> + <div class="flex"></div> + <oobe-text-button id="settings-close-button" inverse + on-tap="onInstallationSettingsCloseClicked_"> + <div i18n-content="eulaSystemInstallationSettingsOkButton"></div> + </oobe-text-button> + </div> + </oobe-dialog> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.js b/chrome/browser/resources/chromeos/login/oobe_eula.js index d649d03c..cf0fc2c 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.js +++ b/chrome/browser/resources/chromeos/login/oobe_eula.js
@@ -36,6 +36,14 @@ }, /** + * The TPM password shown on the installation settings page. + */ + password: { + type: String, + value: null, + }, + + /** * Reference to OOBE screen object. * @type {!OobeTypes.Screen} */ @@ -90,8 +98,19 @@ */ onInstallationSettingsClicked_: function() { chrome.send('eulaOnInstallationSettingsPopupOpened'); - $('popup-overlay').hidden = false; - $('installation-settings-ok-button').focus(); + this.$.eulaDialog.hidden = true; + this.$.installationSettingsDialog.hidden = false; + this.$['settings-close-button'].focus(); + }, + + /** + * On-tap event handler for the close button on installation settings page. + * + * @private + */ + onInstallationSettingsCloseClicked_: function() { + this.$.installationSettingsDialog.hidden = true; + this.$.eulaDialog.hidden = false; }, /** @@ -112,4 +131,22 @@ onEulaBackButtonPressed_: function() { chrome.send('login.EulaScreen.userActed', ['back-button']); }, + + /** + * Returns true if the TPM password hasn't been received. + * + * @private + */ + isWaitingForPassword_: function(password) { + return password == null; + }, + + /** + * Returns true if the TPM password has been received but it's empty. + * + * @private + */ + isPasswordEmpty_: function(password) { + return password != null && password.length == 0; + }, });
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_eula.js b/chrome/browser/resources/chromeos/login/oobe_screen_eula.js index a0c13a5..3ccac318 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_eula.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_eula.js
@@ -316,6 +316,25 @@ }, /** + * Sets TPM password. + * @param {text} password TPM password to be shown. + */ + setTpmPassword: function(password) { + if (loadTimeData.getString('newOobeUI') == 'on') { + $('oobe-eula-md').password = password; + } else { + $('tpm-busy').hidden = true; + if (password.length) { + $('tpm-password').textContent = password; + $('tpm-password').hidden = false; + } else { + $('tpm-desc').hidden = true; + $('tpm-desc-powerwash').hidden = false; + } + } + }, + + /** * Load Eula into the given webview. Online version is attempted first with * a timeout. If it fails to load, fallback to chrome://terms. The loaded * terms contents is then set to the webview via data url. Webview is
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.css b/chrome/browser/resources/chromeos/login/sync_consent.css index 97cce828..376a1ac 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.css +++ b/chrome/browser/resources/chromeos/login/sync_consent.css
@@ -36,6 +36,10 @@ width: fit-content; } +#syncConsentOverviewDialog .bottom-buttons { + padding: 0 6px; /* = 8px - 2px button border */ +} + /************* Settings Section **************/ #syncConsentSettingsDialog oobe-a11y-option { border-top: var(--sync-consent-dialog-list-item-border);
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js index daa78f7..cd92d7d 100644 --- a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js +++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
@@ -993,12 +993,11 @@ $('author-name').textContent = selectedItem.author; $('author-website').textContent = $('author-website').href = selectedItem.authorWebsite; + var img = $('attribute-image'); chrome.wallpaperPrivate.getThumbnail( selectedItem.baseURL, selectedItem.source, data => { - var img = $('attribute-image'); if (data) { WallpaperUtil.displayImage(img, data, null /*opt_callback=*/); - img.hidden = false; } else { // The only known case for hitting this branch is when showing the // wallpaper picker for the first time after OOBE, the |saveThumbnail| @@ -1016,11 +1015,11 @@ if (xhr.status === 200) { WallpaperUtil.displayImage( img, xhr.response, null /*opt_callback=*/); - img.hidden = false; } }); } }); + img.hidden = false; $('wallpaper-attribute').hidden = false; };
diff --git a/chrome/browser/resources/print_preview/new/advanced_settings_dialog.html b/chrome/browser/resources/print_preview/new/advanced_settings_dialog.html index 4715b045..91e920b53 100644 --- a/chrome/browser/resources/print_preview/new/advanced_settings_dialog.html +++ b/chrome/browser/resources/print_preview/new/advanced_settings_dialog.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="../data/destination.html"> <link rel="import" href="advanced_settings_item.html"> @@ -10,7 +11,8 @@ <link rel="import" href="search_dialog_css.html"> <dom-module id="print-preview-advanced-dialog"> - <style include="print-preview-shared search-dialog button"></style> + <style include="print-preview-shared search-dialog button cr-hidden-style"> + </style> <template> <dialog is="cr-dialog" id="dialog" on-close="onCloseOrCancel_"> <div slot="title"> @@ -24,11 +26,14 @@ <div slot="body"> <template is="dom-repeat" items="[[destination.capabilities.printer.vendor_capability]]"> - <print-preview-advanced-settings-item - search-query="[[searchQuery_]]" capability="[[item]]" + <print-preview-advanced-settings-item capability="[[item]]" settings="[[settings]]"> </print-preview-advanced-settings-item> </template> + <div class="no-settings-match-hint" + hidden$="[[!shouldShowHint_(hasMatching_)]]"> + $i18n{noAdvancedSettingsMatchSearchHint} + </div> </div> <div slot="button-container"> <button on-click="onCancelButtonClick_">$i18n{cancel}</button>
diff --git a/chrome/browser/resources/print_preview/new/advanced_settings_dialog.js b/chrome/browser/resources/print_preview/new/advanced_settings_dialog.js index 471a66c..989de5b 100644 --- a/chrome/browser/resources/print_preview/new/advanced_settings_dialog.js +++ b/chrome/browser/resources/print_preview/new/advanced_settings_dialog.js
@@ -16,11 +16,43 @@ type: Object, value: null, }, + + /** @private {boolean} */ + hasMatching_: { + type: Boolean, + notify: true, + computed: 'computeHasMatching_(searchQuery_)', + }, + }, + + /** + * @return {boolean} Whether there is a setting matching the query. + * @private + */ + computeHasMatching_: function() { + const listItems = this.shadowRoot.querySelectorAll( + 'print-preview-advanced-settings-item'); + let hasMatch = false; + listItems.forEach(item => { + const matches = item.hasMatch(this.searchQuery_); + item.hidden = !matches; + hasMatch = hasMatch || matches; + item.updateHighlighting(this.searchQuery_); + }); + return hasMatch; + }, + + /** + * @return {boolean} Whether the no matching settings hint should be shown. + * @private + */ + shouldShowHint_: function() { + return !!this.searchQuery_ && !this.hasMatching_; }, /** @private */ onCloseOrCancel_: function() { - if (this.searchQuery) + if (this.searchQuery_) this.$.searchBox.setValue(''); },
diff --git a/chrome/browser/resources/print_preview/new/advanced_settings_item.html b/chrome/browser/resources/print_preview/new/advanced_settings_item.html index 6897d3c..af531c7 100644 --- a/chrome/browser/resources/print_preview/new/advanced_settings_item.html +++ b/chrome/browser/resources/print_preview/new/advanced_settings_item.html
@@ -1,16 +1,18 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/search_highlight_style_css.html"> <link rel="import" href="../print_preview_utils.html"> <link rel="import" href="../data/destination.html"> +<link rel="import" href="highlight_utils.html"> <link rel="import" href="print_preview_shared_css.html"> <link rel="import" href="select_css.html"> <link rel="import" href="settings_behavior.html"> <dom-module id="print-preview-advanced-settings-item"> - <style include="print-preview-shared select"> + <style include="print-preview-shared select search-highlight-style"> :host { display: flex; + position: relative; } :host > * { @@ -41,23 +43,26 @@ } </style> <template> - <label class="label">[[getDisplayName_(capability)]]</label> - <span class="value"> + <label class="label searchable">[[getDisplayName_(capability)]]</label> + <div class="value"> <template is="dom-if" if="[[isCapabilityTypeSelect_(capability)]]" restamp> - <select on-change="onUserInput_"> - <template is="dom-repeat" items="[[capability.select_cap.option]]"> - <option text="[[getDisplayName_(item)]]" value="[[item.value]]" - selected="[[isOptionSelected_(item, currentValue_)]]"> - </option> - </template> - </select> + <div> + <select on-change="onUserInput_"> + <template is="dom-repeat" items="[[capability.select_cap.option]]"> + <option class="searchable" text="[[getDisplayName_(item)]]" + value="[[item.value]]" + selected="[[isOptionSelected_(item, currentValue_)]]"> + </option> + </template> + </select> + </div> </template> <span hidden$="[[isCapabilityTypeSelect_(capability)]]"> <input type="text" on-input="onUserInput_" placeholder="[[getCapabilityPlaceholder_(capability)]]"> </span> - </span> + </div> </template> <script src="advanced_settings_item.js"></script> </dom-module>
diff --git a/chrome/browser/resources/print_preview/new/advanced_settings_item.js b/chrome/browser/resources/print_preview/new/advanced_settings_item.js index cd626f7..3de026d 100644 --- a/chrome/browser/resources/print_preview/new/advanced_settings_item.js +++ b/chrome/browser/resources/print_preview/new/advanced_settings_item.js
@@ -11,9 +11,6 @@ /** @type {!print_preview.VendorCapability} */ capability: Object, - /** @type {?RegExp} */ - searchQuery: Object, - /** @private {(number | string | boolean)} */ currentValue_: { type: Object, @@ -25,6 +22,9 @@ 'updateFromSettings_(capability, settings.vendorItems.value)', ], + /** @private {boolean} */ + highlighted_: false, + /** @private */ updateFromSettings_: function() { const settings = this.getSetting('vendorItems').value; @@ -87,10 +87,12 @@ */ getCapabilityPlaceholder_: function() { if (this.capability.type == 'TYPED_VALUE' && - this.capability.typed_value_cap) { + this.capability.typed_value_cap && + this.capability.typed_value_cap.default != undefined) { return this.capability.typed_value_cap.default.toString() || ''; } - if (this.capability.type == 'RANGE' && this.capability.range_cap) + if (this.capability.type == 'RANGE' && this.capability.range_cap && + this.capability.range_cap.default != undefined) return this.capability.range_cap.default.toString() || ''; return ''; }, @@ -106,6 +108,26 @@ }, /** + * @param {?RegExp} query The current search query. + * @return {boolean} Whether the item has a match for the query. + */ + hasMatch: function(query) { + if (!query || this.getDisplayName_(this.capability).match(query)) + return true; + + if (!this.isCapabilityTypeSelect_()) + return false; + + for (let option of + /** @type {!Array<!print_preview.VendorCapabilitySelectOption>} */ ( + this.capability.select_cap.option)) { + if (this.getDisplayName_(option).match(query)) + return true; + } + return false; + }, + + /** * @param {!Event} e Event containing the new value. * @private */ @@ -119,4 +141,14 @@ getCurrentValue: function() { return this.currentValue_; }, + + /** + * @param {?RegExp} query The current search query. + * @return {boolean} Whether the current query is a match for this item. + */ + updateHighlighting: function(query) { + this.highlighted_ = + print_preview.updateHighlights(this, query, this.highlighted_); + return this.highlighted_ || !query; + }, });
diff --git a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp index 9065d5f2..e75ada553 100644 --- a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp +++ b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp
@@ -208,7 +208,7 @@ { 'target_name': 'destination_list_item', 'dependencies': [ - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:search_highlight_utils', + 'highlight_utils', '../data/compiled_resources2.gyp:destination', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], @@ -228,6 +228,7 @@ { 'target_name': 'advanced_settings_item', 'dependencies': [ + 'highlight_utils', '../compiled_resources2.gyp:print_preview_utils', '../data/compiled_resources2.gyp:destination', 'settings_behavior', @@ -242,6 +243,13 @@ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, { + 'target_name': 'highlight_utils', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:search_highlight_utils', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'model', 'dependencies': [ 'settings_behavior',
diff --git a/chrome/browser/resources/print_preview/new/destination_list_item.html b/chrome/browser/resources/print_preview/new/destination_list_item.html index 468c0b6..ad4503b6 100644 --- a/chrome/browser/resources/print_preview/new/destination_list_item.html +++ b/chrome/browser/resources/print_preview/new/destination_list_item.html
@@ -1,9 +1,9 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> -<link rel="import" href="chrome://resources/html/search_highlight_utils.html"> <link rel="import" href="../native_layer.html"> <link rel="import" href="../data/destination.html"> +<link rel="import" href="highlight_utils.html"> <link rel="import" href="print_preview_shared_css.html"> <dom-module id="print-preview-destination-list-item">
diff --git a/chrome/browser/resources/print_preview/new/destination_list_item.js b/chrome/browser/resources/print_preview/new/destination_list_item.js index f205a01..7e790c0 100644 --- a/chrome/browser/resources/print_preview/new/destination_list_item.js +++ b/chrome/browser/resources/print_preview/new/destination_list_item.js
@@ -52,37 +52,7 @@ /** @private */ updateHighlighting_: function() { - if (this.highlighted_) { - cr.search_highlight_utils.findAndRemoveHighlights(this); - this.highlighted_ = false; - } - - if (!this.searchQuery) - return; - - this.shadowRoot.querySelectorAll('.searchable').forEach(element => { - element.childNodes.forEach(node => { - if (node.nodeType != Node.TEXT_NODE) - return; - - const textContent = node.nodeValue.trim(); - if (textContent.length == 0) - return; - - if (this.searchQuery.test(textContent)) { - // Don't highlight <select> nodes, yellow rectangles can't be - // displayed within an <option>. - // TODO(rbpotter): solve issue below before adding advanced - // settings so that this function can be re-used. - // TODO(dpapad): highlight <select> controls with a search bubble - // instead. - if (node.parentNode.nodeName != 'OPTION') { - cr.search_highlight_utils.highlight( - node, textContent.split(this.searchQuery)); - this.highlighted_ = true; - } - } - }); - }); + this.highlighted_ = print_preview.updateHighlights( + this, this.searchQuery, this.highlighted_); }, });
diff --git a/chrome/browser/resources/print_preview/new/highlight_utils.html b/chrome/browser/resources/print_preview/new/highlight_utils.html new file mode 100644 index 0000000..ad6c804 --- /dev/null +++ b/chrome/browser/resources/print_preview/new/highlight_utils.html
@@ -0,0 +1,3 @@ +<link rel="import" href="chrome://resources/html/search_highlight_utils.html"> + +<script src="highlight_utils.js"></script>
diff --git a/chrome/browser/resources/print_preview/new/highlight_utils.js b/chrome/browser/resources/print_preview/new/highlight_utils.js new file mode 100644 index 0000000..0a8df2f4 --- /dev/null +++ b/chrome/browser/resources/print_preview/new/highlight_utils.js
@@ -0,0 +1,60 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('print_preview', function() { + 'use strict'; + + /** + * @param {!HTMLElement} element The element to update. Element should have a + * shadow root. + * @param {?RegExp} query The current search query + * @param {boolean} wasHighlighted Whether the element was previously + * highlighted. + * @return {boolean} Whether the element is highlighted after the update. + */ + function updateHighlights(element, query, wasHighlighted) { + if (wasHighlighted) { + cr.search_highlight_utils.findAndRemoveHighlights(element); + cr.search_highlight_utils.findAndRemoveBubbles(element); + } + + if (!query) + return false; + + let isHighlighted = false; + element.shadowRoot.querySelectorAll('.searchable').forEach(childElement => { + childElement.childNodes.forEach(node => { + if (node.nodeType != Node.TEXT_NODE) + return; + + const textContent = node.nodeValue.trim(); + if (textContent.length == 0) + return; + + if (query.test(textContent)) { + isHighlighted = true; + // Don't highlight <select> nodes, yellow rectangles can't be + // displayed within an <option>. + if (node.parentNode.nodeName != 'OPTION') { + cr.search_highlight_utils.highlight(node, textContent.split(query)); + } else { + const selectNode = node.parentNode.parentNode; + // The bubble should be parented by the select node's parent. + // Note: The bubble's ::after element, a yellow arrow, will not + // appear correctly in print preview without SPv175 enabled. See + // https://crbug.com/817058. + cr.search_highlight_utils.highlightControlWithBubble( + /** @type {!HTMLElement} */ (assert(selectNode.parentNode)), + textContent.match(query)[0]); + } + } + }); + }); + return isHighlighted; + } + + return { + updateHighlights: updateHighlights, + }; +});
diff --git a/chrome/browser/resources/print_preview/print_preview_resources.grd b/chrome/browser/resources/print_preview/print_preview_resources.grd index eaa94ed..089ce3f 100644 --- a/chrome/browser/resources/print_preview/print_preview_resources.grd +++ b/chrome/browser/resources/print_preview/print_preview_resources.grd
@@ -281,6 +281,12 @@ <structure name="IDR_PRINT_PREVIEW_NEW_PRINT_PREVIEW_SEARCH_BOX_JS" file="new/print_preview_search_box.js" type="chrome_html" /> + <structure name="IDR_PRINT_PREVIEW_NEW_HIGHLIGHT_UTILS_HTML" + file="new/highlight_utils.html" + type="chrome_html" /> + <structure name="IDR_PRINT_PREVIEW_NEW_HIGHLIGHT_UTILS_JS" + file="new/highlight_utils.js" + type="chrome_html" /> <structure name="IDR_PRINT_PREVIEW_NEW_PRINT_PREVIEW_SHARED_CSS_HTML" file="new/print_preview_shared_css.html" type="chrome_html"
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html index 412b93f2..9053116b1 100644 --- a/chrome/browser/resources/settings/about_page/about_page.html +++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -96,12 +96,22 @@ </div> <div class="settings-box two-line"> <!-- TODO(dpapad): Investigate why vulcanize does not handle well - a new line after "getIconSrc_(", causes incorrect src URL --> + a new line after "getThrobberSrcIfUpdating_(", causes incorrect + src URL --> + <!-- Set the icon from the iconset (when it's obsolete/EOL and + when update is done) or set the src (when it's updating). --> <iron-icon - hidden="[[!showUpdateStatus_]]" - icon$="[[getIcon_( + hidden="[[!shouldShowIcons_(showUpdateStatus_)]]" +<if expr="not chromeos"> + icon$="[[getUpdateStatusIcon_( obsoleteSystemInfo_, currentUpdateStatusEvent_)]]" - src="[[getIconSrc_(obsoleteSystemInfo_, currentUpdateStatusEvent_)]]"> + src="[[getThrobberSrcIfUpdating_(obsoleteSystemInfo_, currentUpdateStatusEvent_)]]"> +</if> +<if expr="chromeos"> + icon$="[[getUpdateStatusIcon_( + hasEndOfLife_, currentUpdateStatusEvent_)]]" + src="[[getThrobberSrcIfUpdating_(hasEndOfLife_, currentUpdateStatusEvent_)]]"> +</if> </iron-icon> <div class="start padded"> <div id="updateStatusMessage" hidden="[[!showUpdateStatus_]]"> @@ -121,6 +131,7 @@ $i18n{learnMore} </a> </div> +<if expr="not chromeos"> <span id="deprecationWarning" hidden="[[!obsoleteSystemInfo_.obsolete]]"> $i18n{aboutObsoleteSystem} @@ -128,6 +139,15 @@ $i18n{learnMore} </a> </span> +</if> +<if expr="chromeos"> + <div id="endOfLifeMessageContainer" hidden="[[!hasEndOfLife_]]"> + $i18n{endOfLifeMessage} + <a href="$i18n{endOfLifeLearnMoreURL}" target="_blank"> + $i18n{learnMore} + </a> + </div> +</if> <div class="secondary">$i18n{aboutBrowserVersion}</div> </div> <div class="separator" hidden="[[!showButtonContainer_]]"></div>
diff --git a/chrome/browser/resources/settings/about_page/about_page.js b/chrome/browser/resources/settings/about_page/about_page.js index beecac1..d2dbea9b 100644 --- a/chrome/browser/resources/settings/about_page/about_page.js +++ b/chrome/browser/resources/settings/about_page/about_page.js
@@ -34,6 +34,9 @@ /** @private {?RegulatoryInfo} */ regulatoryInfo_: Object, + + /** @private */ + hasEndOfLife_: Boolean, // </if> // <if expr="_google_chrome and is_macosx"> @@ -41,6 +44,7 @@ promoteUpdaterStatus_: Object, // </if> + // <if expr="not chromeos"> /** @private {!{obsolete: boolean, endOfLine: boolean}} */ obsoleteSystemInfo_: { type: Object, @@ -51,6 +55,7 @@ }; }, }, + // </if> /** @private */ showUpdateStatus_: Boolean, @@ -73,7 +78,7 @@ showCheckUpdates_: { type: Boolean, computed: 'computeShowCheckUpdates_(' + - 'currentUpdateStatusEvent_, hasCheckedForUpdates_)', + 'currentUpdateStatusEvent_, hasCheckedForUpdates_, hasEndOfLife_)', }, /** @private {!Map<string, string>} */ @@ -117,7 +122,7 @@ // <if expr="chromeos"> 'updateShowUpdateStatus_(' + - 'obsoleteSystemInfo_, currentUpdateStatusEvent_,' + + 'hasEndOfLife_, currentUpdateStatusEvent_,' + 'hasCheckedForUpdates_)', 'updateShowRelaunch_(currentUpdateStatusEvent_, targetChannel_,' + 'currentChannel_)', @@ -155,6 +160,10 @@ this.aboutBrowserProxy_.getRegulatoryInfo().then(info => { this.regulatoryInfo_ = info; }); + + this.aboutBrowserProxy_.getHasEndOfLife().then(result => { + this.hasEndOfLife_ = result; + }); // </if> // <if expr="not chromeos"> this.startListening_(); @@ -250,10 +259,22 @@ this.showUpdateStatus_ = false; return; } + + // Do not show "updated" status if the device is end of life. + if (this.hasEndOfLife_) { + this.showUpdateStatus_ = false; + return; + } + // </if> + + // <if expr="not chromeos"> + if (this.obsoleteSystemInfo_.endOfLine) { + this.showUpdateStatus_ = false; + return; + } // </if> this.showUpdateStatus_ = - this.currentUpdateStatusEvent_.status != UpdateStatus.DISABLED && - !this.obsoleteSystemInfo_.endOfLine; + this.currentUpdateStatusEvent_.status != UpdateStatus.DISABLED; }, /** @@ -353,11 +374,21 @@ * @return {?string} * @private */ - getIcon_: function() { + getUpdateStatusIcon_: function() { + // <if expr="chromeos"> + // If Chrome OS has reached end of life, display a special icon and + // ignore UpdateStatus. + if (this.hasEndOfLife_) { + return 'settings:end-of-life'; + } + // </if> + + // <if expr="not chromeos"> // If this platform has reached the end of the line, display an error icon // and ignore UpdateStatus. if (this.obsoleteSystemInfo_.endOfLine) return 'settings:error'; + // </if> switch (this.currentUpdateStatusEvent_.status) { case UpdateStatus.DISABLED_BY_ADMIN: @@ -376,9 +407,17 @@ * @return {?string} * @private */ - getIconSrc_: function() { + getThrobberSrcIfUpdating_: function() { + // <if expr="chromeos"> + if (this.hasEndOfLife_) { + return null; + } + // </if> + + // <if expr="not chromeos"> if (this.obsoleteSystemInfo_.endOfLine) return null; + // </if> switch (this.currentUpdateStatusEvent_.status) { case UpdateStatus.CHECKING: @@ -440,6 +479,11 @@ * @private */ computeShowCheckUpdates_: function() { + // Disable update button if the device is end of life. + if (this.hasEndOfLife_) { + return false; + } + // Enable the update button if we are in a stale 'updated' status or // update has failed. Disable it otherwise. const staleUpdatedStatus = @@ -501,4 +545,20 @@ this.aboutBrowserProxy_.openFeedbackDialog(); }, // </if> + + /** + * @return {boolean} + * @private + */ + shouldShowIcons_: function() { + // <if expr="chromeos"> + if (this.hasEndOfLife_) + return true; + // </if> + // <if expr="not chromeos"> + if (this.obsoleteSystemInfo_.endOfLine) + return true; + // </if> + return this.showUpdateStatus_; + }, });
diff --git a/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js b/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js index 78a6565..c074d7e 100644 --- a/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js +++ b/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js
@@ -198,6 +198,13 @@ getRegulatoryInfo() {} /** + * Checks if the device has reached end-of-life status and will no longer + * receive updates. + * @return {!Promise<boolean>} + */ + getHasEndOfLife() {} + + /** * Request TPM firmware update status from the browser. It results in one or * more 'tpm-firmware-update-status-changed' WebUI events. */ @@ -279,6 +286,11 @@ } /** @override */ + getHasEndOfLife() { + return cr.sendWithPromise('getHasEndOfLife'); + } + + /** @override */ refreshTPMFirmwareUpdateStatus() { chrome.send('refreshTPMFirmwareUpdateStatus'); }
diff --git a/chrome/browser/resources/settings/compiled_resources2.gyp b/chrome/browser/resources/settings/compiled_resources2.gyp index 645a93b9..f56f7eb 100644 --- a/chrome/browser/resources/settings/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/compiled_resources2.gyp
@@ -80,7 +80,7 @@ 'default_browser_page/compiled_resources2.gyp:*', 'device_page/compiled_resources2.gyp:*', 'downloads_page/compiled_resources2.gyp:*', - 'incompatible_software_page/compiled_resources2.gyp:*', + 'incompatible_applications_page/compiled_resources2.gyp:*', 'internet_page/compiled_resources2.gyp:*', 'languages_page/compiled_resources2.gyp:*', 'on_startup_page/compiled_resources2.gyp:*',
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chrome/browser/resources/settings/controls/settings_toggle_button.html index 145cc4c..2277abc6 100644 --- a/chrome/browser/resources/settings/controls/settings_toggle_button.html +++ b/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> @@ -29,7 +30,7 @@ } :host([elide-label]) .label { - @apply --settings-text-elide; + @apply --cr-text-elide; } #outerRow {
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html index 4fae987..bf9a000 100644 --- a/chrome/browser/resources/settings/icons.html +++ b/chrome/browser/resources/settings/icons.html
@@ -125,6 +125,7 @@ <g id="volume-up"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"></path></g> <if expr="chromeos"> <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g> + <g id="end-of-life"><path d="M4.574 2.916H4.55l.01.01.014-.01zM2.5 4.968v.023a.18.18 0 0 1 .01-.013l-.01-.01zm14.585 10.49v-.024l-.01.013.01.01zm.223 1.817l-.933-.95-4.106-4.11L8.026 7.99 3.675 3.635l-.942-.941-.712-.713L1 3.002l1.733 1.733A9.056 9.056 0 0 0 1.05 9.98c0 1.95.628 3.748 1.683 5.22.574.8 1.274 1.501 2.074 2.075a8.918 8.918 0 0 0 5.218 1.684 8.918 8.918 0 0 0 5.218-1.684L16.991 19l1.02-1.021-.703-.704zM15.243 2.684A8.922 8.922 0 0 0 10.025 1a8.922 8.922 0 0 0-5.218 1.684c-.005.003 4.135 4.16 4.135 4.16l1.083-1.814L15.042 11h-1.846l4.11 4.214a8.939 8.939 0 0 0 .011-10.456 9.021 9.021 0 0 0-2.074-2.074zM12 15H7.012v-3.989L4.5 11l2.227-1.876L12 14.6v.4z" fill="#DB4437" fill-rule="evenodd"></path></g> </if> <if expr="not chromeos"> <g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"></path></g>
diff --git a/chrome/browser/resources/settings/incompatible_software_page/compiled_resources2.gyp b/chrome/browser/resources/settings/incompatible_applications_page/compiled_resources2.gyp similarity index 79% rename from chrome/browser/resources/settings/incompatible_software_page/compiled_resources2.gyp rename to chrome/browser/resources/settings/incompatible_applications_page/compiled_resources2.gyp index d389736..b64db212 100644 --- a/chrome/browser/resources/settings/incompatible_software_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/incompatible_applications_page/compiled_resources2.gyp
@@ -4,29 +4,29 @@ { 'targets': [ { - 'target_name': 'incompatible_software_browser_proxy', + 'target_name': 'incompatible_applications_browser_proxy', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, { - 'target_name': 'incompatible_software_page', + 'target_name': 'incompatible_applications_page', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', - 'incompatible_software_browser_proxy', + 'incompatible_applications_browser_proxy', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, { - 'target_name': 'incompatible_software_item', + 'target_name': 'incompatible_application_item', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', - 'incompatible_software_browser_proxy', + 'incompatible_applications_browser_proxy', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_item.html b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html similarity index 74% rename from chrome/browser/resources/settings/incompatible_software_page/incompatible_software_item.html rename to chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html index cfeeab3..1f8027a 100644 --- a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_item.html +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html
@@ -4,9 +4,9 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="../settings_shared_css.html"> -<link rel="import" href="incompatible_software_browser_proxy.html"> +<link rel="import" href="incompatible_applications_browser_proxy.html"> -<dom-module id="incompatible-software-item"> +<dom-module id="incompatible-application-item"> <template> <style include="settings-shared"> :host { @@ -14,12 +14,12 @@ } </style> <div class="list-item"> - <div class="start">[[softwareName]]</div> + <div class="start">[[applicationName]]</div> <div class="separator"></div> <paper-button class="primary-button" on-click="onActionTap_"> [[getActionName_(actionType)]] </paper-button> </div> </template> - <script src="incompatible_software_item.js"></script> + <script src="incompatible_application_item.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js new file mode 100644 index 0000000..72dd7f1 --- /dev/null +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js
@@ -0,0 +1,103 @@ +// 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. + +/** + * @fileoverview + * 'incompatible-application-item' represents one item in a "list-box" of + * incompatible applications, as defined in + * chrome/browser/conflicts/problematic_programs_updater_win.h. + * This element contains a button that can be used to remove or update the + * incompatible application, depending on the value of the action-type property. + * + * Example usage: + * + * <div class="list-box"> + * <incompatible-application-item + * application-name="Google Chrome" + * action-type="1" + * action-url="https://www.google.com/chrome/more-info"> + * </incompatible-application-item> + * </div> + * + * or + * + * <div class="list-box"> + * <template is="dom-repeat" items="[[applications]]" as="application"> + * <incompatible-application-item + * application-name="[[application.name]]" + * action-type="[[application.actionType]]" + * action-url="[[application.actionUrl]]"> + * </incompatible-application-item> + * </template> + * </div> + */ + +Polymer({ + is: 'incompatible-application-item', + + behaviors: [I18nBehavior], + + properties: { + /** + * The name of the application to be displayed. Also used for the UNINSTALL + * action, where the name is passed to the startProgramUninstallation() + * call. + */ + applicationName: String, + + /** + * The type of the action to be taken on this incompatible application. Must + * be one of BlacklistMessageType in + * chrome/browser/conflicts/proto/module_list.proto. + * @type {!settings.ActionTypes} + */ + actionType: Number, + + /** + * For the actions MORE_INFO and UPGRADE, this is the URL that must be + * opened when the action button is tapped. + */ + actionUrl: String, + }, + + /** @private {settings.IncompatibleApplicationsBrowserProxy} */ + browserProxy_: null, + + /** @override */ + created: function() { + this.browserProxy_ = + settings.IncompatibleApplicationsBrowserProxyImpl.getInstance(); + }, + + /** + * Executes the action for this incompatible application, depending on + * actionType. + * @private + */ + onActionTap_: function() { + if (this.actionType === settings.ActionTypes.UNINSTALL) { + this.browserProxy_.startProgramUninstallation(this.applicationName); + } else if ( + this.actionType === settings.ActionTypes.MORE_INFO || + this.actionType === settings.ActionTypes.UPGRADE) { + this.browserProxy_.openURL(this.actionUrl); + } else { + assertNotReached(); + } + }, + + /** + * @return {string} The label that should be applied to the action button. + * @private + */ + getActionName_: function(actionType) { + if (actionType === settings.ActionTypes.UNINSTALL) + return this.i18n('incompatibleApplicationsRemoveButton'); + if (actionType === settings.ActionTypes.MORE_INFO) + return this.i18n('learnMore'); + if (actionType === settings.ActionTypes.UPGRADE) + return this.i18n('incompatibleApplicationsUpdateButton'); + assertNotReached(); + }, +});
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.html b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.html new file mode 100644 index 0000000..8d55a23 --- /dev/null +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="incompatible_applications_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js new file mode 100644 index 0000000..7017e0a46 --- /dev/null +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js
@@ -0,0 +1,122 @@ +// 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. + +/** + * @fileoverview A helper object used from the Incompatible Applications section + * to interact with the browser. + */ + +cr.exportPath('settings'); + +/** + * All possible actions to take on an incompatible application. + * + * Must be kept in sync with BlacklistMessageType in + * chrome/browser/conflicts/proto/module_list.proto + * @readonly + * @enum {number} + */ +settings.ActionTypes = { + UNINSTALL: 0, + MORE_INFO: 1, + UPGRADE: 2, +}; + +/** + * @typedef {{ + * name: string, + * actionType: {settings.ActionTypes}, + * actionUrl: string, + * }} + */ +settings.IncompatibleApplication; + +cr.define('settings', function() { + /** @interface */ + class IncompatibleApplicationsBrowserProxy { + /** + * Get the list of incompatible applications. + * @return {!Promise<!Array<!settings.IncompatibleApplication>>} + */ + requestIncompatibleApplicationsList() {} + + /** + * Launches the Apps & Features page that allows uninstalling 'programName'. + * @param {string} programName + */ + startProgramUninstallation(programName) {} + + /** + * Opens the specified URL in a new tab. + * @param {!string} url + */ + openURL(url) {} + + /** + * Requests the plural string for the subtitle of the Incompatible + * Applications subpage. + * @param {number} numApplications + * @return {!Promise<string>} + */ + getSubtitlePluralString(numApplications) {} + + /** + * Requests the plural string for the subtitle of the Incompatible + * Applications subpage, when the user does not have administrator rights. + * @param {number} numApplications + * @return {!Promise<string>} + */ + getSubtitleNoAdminRightsPluralString(numApplications) {} + + /** + * Requests the plural string for the title of the list of Incompatible + * Applications. + * @param {number} numApplications + * @return {!Promise<string>} + */ + getListTitlePluralString(numApplications) {} + } + + /** @implements {settings.IncompatibleApplicationsBrowserProxy} */ + class IncompatibleApplicationsBrowserProxyImpl { + /** @override */ + requestIncompatibleApplicationsList() { + return cr.sendWithPromise('requestIncompatibleApplicationsList'); + } + + /** @override */ + startProgramUninstallation(programName) { + chrome.send('startProgramUninstallation', [programName]); + } + + /** @override */ + openURL(url) { + window.open(url); + } + + /** @override */ + getSubtitlePluralString(numApplications) { + return cr.sendWithPromise('getSubtitlePluralString', numApplications); + } + + /** @override */ + getSubtitleNoAdminRightsPluralString(numApplications) { + return cr.sendWithPromise( + 'getSubtitleNoAdminRightsPluralString', numApplications); + } + + /** @override */ + getListTitlePluralString(numApplications) { + return cr.sendWithPromise('getListTitlePluralString', numApplications); + } + } + + cr.addSingletonGetter(IncompatibleApplicationsBrowserProxyImpl); + + return { + IncompatibleApplicationsBrowserProxy: IncompatibleApplicationsBrowserProxy, + IncompatibleApplicationsBrowserProxyImpl: + IncompatibleApplicationsBrowserProxyImpl, + }; +});
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.html b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.html new file mode 100644 index 0000000..efe3fb2 --- /dev/null +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.html
@@ -0,0 +1,44 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> +<link rel="import" href="../settings_shared_css.html"> +<link rel="import" href="incompatible_application_item.html"> +<link rel="import" href="incompatible_applications_browser_proxy.html"> + +<dom-module id="settings-incompatible-applications-page"> + <template> + <style include="settings-shared"></style> + <div class="settings-box first two-line"> + <iron-icon icon="settings:security"></iron-icon> + <div class="middle no-min-width"> + <div hidden$="[[!hasAdminRights_]]"> + [[subtitleText_]] $i18nRaw{incompatibleApplicationsSubpageLearnHow} + </div> + <div hidden$="[[hasAdminRights_]]"> + [[subtitleNoAdminRightsText_]] + </div> + </div> + </div> + <div class="settings-box continuation"> + <div class="secondary">[[listTitleText_]]</div> + </div> + <div id="incompatible-applications-list" class="list-frame vertical-list"> + <template is="dom-repeat" items="[[applications_]]" as="application"> + <incompatible-application-item + hidden$="[[!hasAdminRights_]]" + class="incompatible-application" + application-name="[[application.name]]" + action-type="[[application.type]]" + action-url="[[application.url]]"> + </incompatible-application-item> + <div hidden$="[[hasAdminRights_]]" + class="list-item incompatible-application"> + [[application.name]] + </div> + </template> + </div> + </template> + <script src="incompatible_applications_page.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.js b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.js new file mode 100644 index 0000000..213aa20 --- /dev/null +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.js
@@ -0,0 +1,102 @@ +// 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. + +/** + * @fileoverview + * 'settings-incompatible-applications-page' is the settings subpage containing + * the list of incompatible applications. + * + * Example: + * + * <iron-animated-pages> + * <settings-incompatible-applications-page"> + * </settings-incompatible-applications-page> + * ... other pages ... + * </iron-animated-pages> + */ + +Polymer({ + is: 'settings-incompatible-applications-page', + + behaviors: [I18nBehavior], + + properties: { + /** + * Indicates if the current user has administrator rights. + * @private + */ + hasAdminRights_: { + type: Boolean, + value: function() { + return loadTimeData.getBoolean('hasAdminRights'); + }, + }, + + /** + * The list of all the incompatible applications. + * @private {Array<settings.IncompatibleApplication>} + */ + applications_: Array, + + /** + * The text for the subtitle of the subpage. + * @private + */ + subtitleText_: { + type: String, + value: '', + }, + + /** + * The text for the subtitle of the subpage, when the user does not have + * administrator rights. + * @private + */ + subtitleNoAdminRightsText_: { + type: String, + value: '', + }, + + /** + * The text for the title of the list of incompatible applications. + * @private + */ + listTitleText_: { + type: String, + value: '', + }, + }, + + /** @override */ + ready: function() { + settings.IncompatibleApplicationsBrowserProxyImpl.getInstance() + .requestIncompatibleApplicationsList() + .then(list => { + this.applications_ = list; + this.updatePluralStrings_(); + }); + }, + + /** + * Updates the texts of the Incompatible Applications subpage that depends on + * the length of |applications_|. + * @private + */ + updatePluralStrings_: function() { + const browserProxy = + settings.IncompatibleApplicationsBrowserProxyImpl.getInstance(); + const numApplications = this.applications_.length; + Promise + .all([ + browserProxy.getSubtitlePluralString(numApplications), + browserProxy.getSubtitleNoAdminRightsPluralString(numApplications), + browserProxy.getListTitlePluralString(numApplications), + ]) + .then(strings => { + this.subtitleText_ = strings[0]; + this.subtitleNoAdminRightsText_ = strings[1]; + this.listTitleText_ = strings[2]; + }); + }, +});
diff --git a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_browser_proxy.html b/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_browser_proxy.html deleted file mode 100644 index 4aae9a9..0000000 --- a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_browser_proxy.html +++ /dev/null
@@ -1,2 +0,0 @@ -<link rel="import" href="chrome://resources/html/cr.html"> -<script src="incompatible_software_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_browser_proxy.js b/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_browser_proxy.js deleted file mode 100644 index 1e7d6cc7..0000000 --- a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_browser_proxy.js +++ /dev/null
@@ -1,81 +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. - -/** - * @fileoverview A helper object used from the Incompatible Software section to - * interact with the browser. - */ - -cr.exportPath('settings'); - -/** - * All possible actions to take on am incompatible software. - * - * Must be kept in sync with BlacklistMessageType in - * chrome/browser/conflicts/proto/module_list.proto - * @readonly - * @enum {number} - */ -settings.ActionTypes = { - UNINSTALL: 0, - MORE_INFO: 1, - UPGRADE: 2, -}; - -/** - * @typedef {{ - * name: string, - * actionType: {settings.ActionTypes}, - * actionUrl: string, - * }} - */ -settings.IncompatibleSoftware; - -cr.define('settings', function() { - /** @interface */ - class IncompatibleSoftwareBrowserProxy { - /** - * Get the list of incompatible software. - * @return {!Promise<!Array<!settings.IncompatibleSoftware>>} - */ - requestIncompatibleSoftwareList() {} - - /** - * Launches the Apps & Features page that allows uninstalling 'programName'. - * @param {string} programName - */ - startProgramUninstallation(programName) {} - - /** - * Opens the specified URL in a new tab. - * @param {!string} url - */ - openURL(url) {} - } - - /** @implements {settings.IncompatibleSoftwareBrowserProxy} */ - class IncompatibleSoftwareBrowserProxyImpl { - /** @override */ - requestIncompatibleSoftwareList() { - return cr.sendWithPromise('requestIncompatibleSoftwareList'); - } - - /** @override */ - startProgramUninstallation(programName) { - chrome.send('startProgramUninstallation', [programName]); - } - - /** @override */ - openURL(url) { - window.open(url); - } - } - - cr.addSingletonGetter(IncompatibleSoftwareBrowserProxyImpl); - - return { - IncompatibleSoftwareBrowserProxy: IncompatibleSoftwareBrowserProxy, - IncompatibleSoftwareBrowserProxyImpl: IncompatibleSoftwareBrowserProxyImpl, - }; -});
diff --git a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_item.js b/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_item.js deleted file mode 100644 index 2855f8a..0000000 --- a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_item.js +++ /dev/null
@@ -1,103 +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. - -/** - * @fileoverview - * 'incompatible-software-item' represents one item in a "list-box" of - * incompatible software, as defined in - * chrome/browser/conflicts/problematic_programs_updater_win.h. - * This element contains a button that can be used to remove or update the - * incompatible software, depending on the value of the action-type property. - * - * Example usage: - * - * <div class="list-box"> - * <incompatible-software-item - * software-name="Google Chrome" - * action-type="1" - * action-url="https://www.google.com/chrome/more-info"> - * </incompatible-software-item> - * </div> - * - * or - * - * <div class="list-box"> - * <template is="dom-repeat" items="[[softwareList]]" as="software"> - * <incompatible-software-item - * software-name="[[software.name]]" - * action-type="[[software.actionType]]" - * action-url="[[software.actionUrl]]"> - * </incompatible-software-item> - * </template> - * </div> - */ - -Polymer({ - is: 'incompatible-software-item', - - behaviors: [I18nBehavior], - - properties: { - /** - * The name of the software to be displayed. Also used for the UNINSTALL - * action, where the name is passed to the startProgramUninstallation() - * call. - */ - softwareName: String, - - /** - * The type of the action to be taken on this incompatible software. Must be - * one of BlacklistMessageType in - * chrome/browser/conflicts/proto/module_list.proto. - * @type {!settings.ActionTypes} - */ - actionType: Number, - - /** - * For the actions MORE_INFO and UPGRADE, this is the URL that must be - * opened when the action button is tapped. - */ - actionUrl: String, - }, - - /** @private {settings.IncompatibleSoftwareBrowserProxy} */ - browserProxy_: null, - - /** @override */ - created: function() { - this.browserProxy_ = - settings.IncompatibleSoftwareBrowserProxyImpl.getInstance(); - }, - - /** - * Executes the action for this incompatible software, depending on - * actionType. - * @private - */ - onActionTap_: function() { - if (this.actionType === settings.ActionTypes.UNINSTALL) { - this.browserProxy_.startProgramUninstallation(this.softwareName); - } else if ( - this.actionType === settings.ActionTypes.MORE_INFO || - this.actionType === settings.ActionTypes.UPGRADE) { - this.browserProxy_.openURL(this.actionUrl); - } else { - assertNotReached(); - } - }, - - /** - * @return {string} The label that should be applied to the action button. - * @private - */ - getActionName_: function(actionType) { - if (actionType === settings.ActionTypes.UNINSTALL) - return this.i18n('incompatibleSoftwareRemoveButton'); - if (actionType === settings.ActionTypes.MORE_INFO) - return this.i18n('learnMore'); - if (actionType === settings.ActionTypes.UPGRADE) - return this.i18n('incompatibleSoftwareUpdateButton'); - assertNotReached(); - }, -});
diff --git a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_page.html b/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_page.html deleted file mode 100644 index b1d4011d..0000000 --- a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_page.html +++ /dev/null
@@ -1,44 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> -<link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> -<link rel="import" href="../settings_shared_css.html"> -<link rel="import" href="incompatible_software_item.html"> -<link rel="import" href="incompatible_software_browser_proxy.html"> - -<dom-module id="settings-incompatible-software-page"> - <template> - <style include="settings-shared"></style> - <div class="settings-box first two-line"> - <iron-icon icon="settings:security"></iron-icon> - <div class="middle no-min-width"> - <div hidden$="[[!hasAdminRights_]]"> - $i18n{incompatibleSoftwareSubpageSubtitle} $i18nRaw{incompatibleSoftwareSubpageLearnHow} - </div> - <div hidden$="[[hasAdminRights_]]"> - $i18n{incompatibleSoftwareSubpageSubtitleNoAdminRights} - </div> - </div> - </div> - <div class="settings-box continuation"> - <div class="secondary">$i18n{incompatibleSoftwareListTitle}</div> - </div> - <div id="incompatible-software-list" class="list-frame vertical-list"> - <template is="dom-repeat" items="[[softwareList_]]" as="software"> - <incompatible-software-item - hidden$="[[!hasAdminRights_]]" - class="incompatible-software" - software-name="[[software.name]]" - action-type="[[software.type]]" - action-url="[[software.url]]"> - </incompatible-software-item> - <div hidden$="[[hasAdminRights_]]" - class="list-item incompatible-software"> - [[software.name]] - </div> - </template> - </div> - </template> - <script src="incompatible_software_page.js"></script> -</dom-module>
diff --git a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_page.js b/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_page.js deleted file mode 100644 index cdc25a2..0000000 --- a/chrome/browser/resources/settings/incompatible_software_page/incompatible_software_page.js +++ /dev/null
@@ -1,51 +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. - -/** - * @fileoverview - * 'settings-incompatible-software-page' is the settings subpage containing - * the list of incompatible software. - * - * Example: - * - * <iron-animated-pages> - * <settings-incompatible-software-page"> - * </settings-incompatible-software-page> - * ... other pages ... - * </iron-animated-pages> - */ - -Polymer({ - is: 'settings-incompatible-software-page', - - behaviors: [I18nBehavior], - - properties: { - /** - * Indicates if the current user has administrator rights. - * @private - */ - hasAdminRights_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('hasAdminRights'); - }, - }, - - /** - * The list of all the incompatible software. - * @private {Array<settings.IncompatibleSoftware>} - */ - softwareList_: Array, - }, - - /** @override */ - ready: function() { - settings.IncompatibleSoftwareBrowserProxyImpl.getInstance() - .requestIncompatibleSoftwareList() - .then(list => { - this.softwareList_ = list; - }); - }, -});
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.html b/chrome/browser/resources/settings/internet_page/internet_config.html index fe5ff19..01e3cfa 100644 --- a/chrome/browser/resources/settings/internet_page/internet_config.html +++ b/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -32,7 +32,7 @@ share-allow-enable="[[shareAllowEnable_]]" share-default="[[shareDefault_]]" error="{{error_}}" - on-close="close"> + on-close="onClose_"> </network-config> </div>
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.js b/chrome/browser/resources/settings/internet_page/internet_config.js index b6bda81..6aab8e2 100644 --- a/chrome/browser/resources/settings/internet_page/internet_config.js +++ b/chrome/browser/resources/settings/internet_page/internet_config.js
@@ -103,6 +103,16 @@ }, /** + * @param {!Event} event + * @private + */ + onClose_: function(event) { + this.close(); + this.fire('networks-changed'); + event.stopPropagation(); + }, + + /** * @return {string} * @private */
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.html b/chrome/browser/resources/settings/reset_page/reset_page.html index a01ac39..fb4a028f 100644 --- a/chrome/browser/resources/settings/reset_page/reset_page.html +++ b/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -17,7 +17,7 @@ <if expr="_google_chrome and is_win"> <link rel="import" href="../chrome_cleanup_page/chrome_cleanup_page.html"> -<link rel="import" href="../incompatible_software_page/incompatible_software_page.html"> +<link rel="import" href="../incompatible_applications_page/incompatible_applications_page.html"> </if> <dom-module id="settings-reset-page"> @@ -72,17 +72,17 @@ aria-describedby="chromeCleanupSecondary"></button> </div> </template> - <template is="dom-if" if="[[showIncompatibleSoftware_]]" restamp> + <template is="dom-if" if="[[showIncompatibleApplications_]]" restamp> <div class="settings-box" - id="incompatibleSoftwareSubpageTrigger" - on-click="onIncompatibleSoftwareTap_" actionable> + id="incompatibleApplicationsSubpageTrigger" + on-click="onIncompatibleApplicationsTap_" actionable> <div class="start"> - $i18n{incompatibleSoftwareResetCardTitle} + $i18n{incompatibleApplicationsResetCardTitle} </div> <button is="paper-icon-button-light" class="subpage-arrow" - aria-label="$i18n{incompatibleSoftwareResetCardTitle}" - aria-describedby="incompatibleSoftwareSecondary"></button> + aria-label="$i18n{incompatibleApplicationsResetCardTitle}" + aria-describedby="incompatibleApplicationsSecondary"></button> </div> </template> </if> @@ -98,13 +98,13 @@ </settings-subpage> </template> </template> - <template is="dom-if" if="[[showIncompatibleSoftware_]]"> - <template is="dom-if" route-path="/incompatibleSoftware"> - <settings-subpage id="incompatibleSoftwareSubpage" - associated-control="[[$$('#incompatibleSoftwareSubpageTrigger')]]" - page-title="$i18n{incompatibleSoftwareResetCardTitle}"> - <settings-incompatible-software-page> - </settings-incompatible-software-page> + <template is="dom-if" if="[[showIncompatibleApplications_]]"> + <template is="dom-if" route-path="/incompatibleApplications"> + <settings-subpage id="incompatibleApplicationsSubpage" + associated-control="[[$$('#incompatibleApplicationsSubpageTrigger')]]" + page-title="$i18n{incompatibleApplicationsResetCardTitle}"> + <settings-incompatible-applications-page> + </settings-incompatible-applications-page> </settings-subpage> </template> </template>
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.js b/chrome/browser/resources/settings/reset_page/reset_page.js index 93e2762..10082a0b 100644 --- a/chrome/browser/resources/settings/reset_page/reset_page.js +++ b/chrome/browser/resources/settings/reset_page/reset_page.js
@@ -42,10 +42,10 @@ }, /** @private */ - showIncompatibleSoftware_: { + showIncompatibleApplications_: { type: Boolean, value: function() { - return loadTimeData.getBoolean('showIncompatibleSoftware'); + return loadTimeData.getBoolean('showIncompatibleApplications'); }, }, // </if> @@ -101,8 +101,8 @@ }, /** @private */ - onIncompatibleSoftwareTap_: function() { - settings.navigateTo(settings.routes.INCOMPATIBLE_SOFTWARE); + onIncompatibleApplicationsTap_: function() { + settings.navigateTo(settings.routes.INCOMPATIBLE_APPLICATIONS); }, // </if>
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index 279ca6c..68183214 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -36,7 +36,7 @@ * FONTS: (undefined|!settings.Route), * GOOGLE_ASSISTANT: (undefined|!settings.Route), * IMPORT_DATA: (undefined|!settings.Route), - * INCOMPATIBLE_SOFTWARE: (undefined|!settings.Route), + * INCOMPATIBLE_APPLICATIONS: (undefined|!settings.Route), * INPUT_METHODS: (undefined|!settings.Route), * INTERNET: (undefined|!settings.Route), * INTERNET_NETWORKS: (undefined|!settings.Route), @@ -391,9 +391,9 @@ if (loadTimeData.getBoolean('userInitiatedCleanupsEnabled')) { r.CHROME_CLEANUP = r.RESET.createChild('/cleanup'); } - if (loadTimeData.getBoolean('showIncompatibleSoftware')) { - r.INCOMPATIBLE_SOFTWARE = - r.RESET.createChild('/incompatibleSoftware'); + if (loadTimeData.getBoolean('showIncompatibleApplications')) { + r.INCOMPATIBLE_APPLICATIONS = + r.RESET.createChild('/incompatibleApplications'); } // </if> }
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js index 1db1d43..71971fa 100644 --- a/chrome/browser/resources/settings/search_settings.js +++ b/chrome/browser/resources/settings/search_settings.js
@@ -17,9 +17,6 @@ settings.SearchResult; cr.define('settings', function() { - /** @type {string} */ - const SEARCH_BUBBLE_CSS_CLASS = 'search-bubble'; - /** * A CSS attribute indicating that a node should be ignored during searching. * @type {string} @@ -57,11 +54,7 @@ */ function findAndRemoveHighlights_(node) { cr.search_highlight_utils.findAndRemoveHighlights(node); - - const searchBubbles = - node.querySelectorAll('* /deep/ .' + SEARCH_BUBBLE_CSS_CLASS); - for (let j = 0; j < searchBubbles.length; j++) - searchBubbles[j].remove(); + cr.search_highlight_utils.findAndRemoveBubbles(node); } /** @@ -135,44 +128,6 @@ } /** - * Highlights the HTML control that triggers a subpage, by displaying a search - * bubble. - * @param {!HTMLElement} element The element to be highlighted. - * @param {string} rawQuery The search query. - * @private - */ - function highlightAssociatedControl_(element, rawQuery) { - let searchBubble = element.querySelector('.' + SEARCH_BUBBLE_CSS_CLASS); - // If the associated control has already been highlighted due to another - // match on the same subpage, there is no need to do anything. - if (searchBubble) - return; - - searchBubble = document.createElement('div'); - searchBubble.classList.add(SEARCH_BUBBLE_CSS_CLASS); - const innards = document.createElement('div'); - innards.classList.add('search-bubble-innards', 'text-elide'); - innards.textContent = rawQuery; - searchBubble.appendChild(innards); - element.appendChild(searchBubble); - - // Dynamically position the bubble at the edge the associated control - // element. - const updatePosition = function() { - searchBubble.style.top = element.offsetTop + - (innards.classList.contains('above') ? -searchBubble.offsetHeight : - element.offsetHeight) + - 'px'; - }; - updatePosition(); - - searchBubble.addEventListener('mouseover', function() { - innards.classList.toggle('above'); - updatePosition(); - }); - } - - /** * Finds and makes visible the <settings-section> parent of |node|. * @param {!Node} node * @param {string} rawQuery @@ -199,8 +154,10 @@ // Need to add the search bubble after the parent SETTINGS-SECTION has // become visible, otherwise |offsetWidth| returns zero. - if (associatedControl) - highlightAssociatedControl_(associatedControl, rawQuery); + if (associatedControl) { + cr.search_highlight_utils.highlightControlWithBubble( + associatedControl, rawQuery); + } } /** @abstract */
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 0335c70..1a9f7e73 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -326,23 +326,23 @@ type="chrome_html"/> </if> <if expr="is_win and _google_chrome"> - <structure name="IDR_SETTINGS_INCOMPATIBLE_SOFTWARE_PAGE_HTML" - file="incompatible_software_page/incompatible_software_page.html" + <structure name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_PAGE_HTML" + file="incompatible_applications_page/incompatible_applications_page.html" type="chrome_html" /> - <structure name="IDR_SETTINGS_INCOMPATIBLE_SOFTWARE_PAGE_JS" - file="incompatible_software_page/incompatible_software_page.js" + <structure name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_PAGE_JS" + file="incompatible_applications_page/incompatible_applications_page.js" type="chrome_html" /> - <structure name="IDR_SETTINGS_INCOMPATIBLE_SOFTWARE_BROWSER_PROXY_HTML" - file="incompatible_software_page/incompatible_software_browser_proxy.html" + <structure name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_BROWSER_PROXY_HTML" + file="incompatible_applications_page/incompatible_applications_browser_proxy.html" type="chrome_html" /> - <structure name="IDR_SETTINGS_INCOMPATIBLE_SOFTWARE_BROWSER_PROXY_JS" - file="incompatible_software_page/incompatible_software_browser_proxy.js" + <structure name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_BROWSER_PROXY_JS" + file="incompatible_applications_page/incompatible_applications_browser_proxy.js" type="chrome_html" /> - <structure name="IDR_SETTINGS_INCOMPATIBLE_SOFTWARE_INCOMPATIBLE_SOFTWARE_ITEM_HTML" - file="incompatible_software_page/incompatible_software_item.html" + <structure name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_INCOMPATIBLE_APPLICATION_ITEM_HTML" + file="incompatible_applications_page/incompatible_application_item.html" type="chrome_html" /> - <structure name="IDR_SETTINGS_INCOMPATIBLE_SOFTWARE_INCOMPATIBLE_SOFTWARE_ITEM_JS" - file="incompatible_software_page/incompatible_software_item.js" + <structure name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_INCOMPATIBLE_APPLICATION_ITEM_JS" + file="incompatible_applications_page/incompatible_application_item.js" type="chrome_html" /> </if> <structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_BROWSER_PROXY_HTML"
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index c4a18af..8baf075 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/cr_elements/paper_checkbox_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/search_highlight_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="settings_icons_css.html"> @@ -11,7 +12,7 @@ <!-- Common styles for Material Design settings. --> <dom-module id="settings-shared"> <template> - <style include="settings-icons paper-button-style paper-checkbox-style paper-input-style paper-toggle-style cr-shared-style"> + <style include="settings-icons paper-button-style paper-checkbox-style paper-input-style paper-toggle-style cr-shared-style search-highlight-style"> /* Prevent action-links from being selected to avoid accidental * selection when trying to click it. */ a[is=action-link] { @@ -154,7 +155,7 @@ /* See also: .no-min-width below. */ .text-elide { - @apply --settings-text-elide; + @apply --cr-text-elide; } /* By default, flexbox children have min-width calculated to be the width @@ -358,44 +359,6 @@ width: 16px; } - .search-bubble { - /* RGB value matches var(--paper-yellow-500). */ - --search-bubble-color: rgba(255, 235, 59, 0.9); - position: absolute; - z-index: 1; - } - - .search-bubble-innards { - align-items: center; - background-color: var(--search-bubble-color); - border-radius: 2px; - max-width: 100px; - min-width: 64px; - padding: 4px 10px; - text-align: center; - } - - /* Provides the arrow which points at the anchor element. */ - .search-bubble-innards::after { - background-color: var(--search-bubble-color); - content: ''; - height: 10px; - left: calc(50% - 5px); - position: absolute; - top: -5px; - transform: rotate(-45deg); - width: 10px; - z-index: -1; - } - - /* Turns the arrow direction downwards, when the bubble is placed above - * the anchor element */ - .search-bubble-innards.above::after { - bottom: -5px; - top: auto; - transform: rotate(-135deg); - } - .column-header { color: var(--paper-grey-600); font-weight: 500;
diff --git a/chrome/browser/resources/settings/settings_vars_css.html b/chrome/browser/resources/settings/settings_vars_css.html index 595e689..5e9062e 100644 --- a/chrome/browser/resources/settings/settings_vars_css.html +++ b/chrome/browser/resources/settings/settings_vars_css.html
@@ -37,12 +37,6 @@ --settings-row-three-line-min-height: var(--cr-section-three-line-min-height); - --settings-text-elide: { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - }; - --settings-separator-height: var(--cr-separator-height); --settings-separator-line: var(--cr-separator-line);
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 7c5824c..400d620 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -6905,7 +6905,8 @@ } protected: - void SetUpCertVerifier() { + void SetUpCertVerifier(const std::string& host_pattern, + bool already_distrusted) { net::CertVerifyResult verify_result; { base::ScopedAllowBlockingForTesting allow_blocking; @@ -6925,8 +6926,14 @@ GetSPKIHash(intermediate.get())); } - mock_cert_verifier()->AddResultForCert(https_server_.GetCertificate().get(), - verify_result, net::OK); + if (already_distrusted) { + verify_result.cert_status = net::CERT_STATUS_SYMANTEC_LEGACY; + } + + mock_cert_verifier()->set_default_result(net::OK); + mock_cert_verifier()->AddResultForCertAndHost( + https_server_.GetCertificate().get(), host_pattern, verify_result, + already_distrusted ? net::ERR_CERT_SYMANTEC_LEGACY : net::OK); } net::EmbeddedTestServer* https_server() { return &https_server_; } @@ -6941,7 +6948,8 @@ // Tests that the Symantec console message is properly overridden for post-June // 2016 certificates. IN_PROC_BROWSER_TEST_F(SymantecMessageSSLUITest, PostJune2016) { - ASSERT_NO_FATAL_FAILURE(SetUpCertVerifier()); + ASSERT_NO_FATAL_FAILURE( + SetUpCertVerifier("*", false /* already_distrusted */)); ASSERT_TRUE(https_server()->Start()); GURL url(https_server()->GetURL("/ssl/google.html")); WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); @@ -6961,7 +6969,8 @@ // out after many subresource loads. IN_PROC_BROWSER_TEST_F(SymantecMessageSSLUITest, ManySubresources) { content::SetupCrossSiteRedirector(https_server()); - ASSERT_NO_FATAL_FAILURE(SetUpCertVerifier()); + ASSERT_NO_FATAL_FAILURE( + SetUpCertVerifier("*", false /* already_distrusted */)); ASSERT_TRUE(https_server()->Start()); GURL url(https_server()->GetURL("/ssl/page_with_many_subresources.html")); WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); @@ -6987,6 +6996,27 @@ } } +// Tests that the Symantec console message is logged for resources with certs +// that have already been distrusted. +IN_PROC_BROWSER_TEST_F(SymantecMessageSSLUITest, DistrustedSubresources) { + content::SetupCrossSiteRedirector(https_server()); + // Only distrust subresources on *.test, so that the main resource loads + // without an interstitial. + ASSERT_NO_FATAL_FAILURE( + SetUpCertVerifier("*.test", true /* already_distrusted */)); + ASSERT_TRUE(https_server()->Start()); + GURL url(https_server()->GetURL("/ssl/page_with_many_subresources.html")); + WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); + + content::ConsoleObserverDelegate console_observer(tab, "*https://a.test*"); + tab->SetDelegate(&console_observer); + ui_test_utils::NavigateToURL(browser(), url); + ASSERT_FALSE(IsShowingInterstitial(tab)); + console_observer.Wait(); + EXPECT_TRUE( + base::MatchPattern(console_observer.message(), "*has been distrusted*")); +} + // Checks that SimpleURLLoader, which uses services/network/url_loader.cc, goes // through the new NetworkServiceClient interface to deliver cert error // notifications to the browser which then overrides the certificate error.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 4beebd1..4d8cdb49 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2616,8 +2616,8 @@ sources += [ "webui/help/version_updater_win.cc", "webui/help/version_updater_win.h", - "webui/settings/incompatible_software_handler_win.cc", - "webui/settings/incompatible_software_handler_win.h", + "webui/settings/incompatible_applications_handler_win.cc", + "webui/settings/incompatible_applications_handler_win.h", ] deps += [ "//google_update" ] } else {
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc index ff00d2d..3e9fa7d 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -301,11 +301,11 @@ AppSearchProvider::AppSearchProvider(Profile* profile, AppListControllerDelegate* list_controller, - std::unique_ptr<base::Clock> clock, + base::Clock* clock, AppListModelUpdater* model_updater) : list_controller_(list_controller), model_updater_(model_updater), - clock_(std::move(clock)), + clock_(clock), update_results_factory_(this) { data_sources_.emplace_back( std::make_unique<ExtensionDataSource>(profile, this));
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.h b/chrome/browser/ui/app_list/search/app_search_provider.h index c25df56..f70ee29 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider.h +++ b/chrome/browser/ui/app_list/search/app_search_provider.h
@@ -31,9 +31,13 @@ class DataSource; using Apps = std::vector<std::unique_ptr<App>>; + // |clock| should be used by tests that needs to overrides the time. + // Otherwise, pass a base::DefaultClock instance. This doesn't take the + // ownership of the clock. |clock| must outlive the AppSearchProvider + // instance. AppSearchProvider(Profile* profile, AppListControllerDelegate* list_controller, - std::unique_ptr<base::Clock> clock, + base::Clock* clock, AppListModelUpdater* model_updater); ~AppSearchProvider() override; @@ -57,7 +61,7 @@ base::string16 query_; Apps apps_; AppListModelUpdater* const model_updater_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; std::vector<std::unique_ptr<DataSource>> data_sources_; base::WeakPtrFactory<AppSearchProvider> update_results_factory_;
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc index b8aebea0..4b0ce59 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
@@ -68,10 +68,9 @@ } void CreateSearch() { - std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock()); - clock->SetNow(kTestCurrentTime); - app_search_.reset(new AppSearchProvider( - profile_.get(), nullptr, std::move(clock), model_updater_.get())); + clock_.SetNow(kTestCurrentTime); + app_search_.reset(new AppSearchProvider(profile_.get(), nullptr, &clock_, + model_updater_.get())); } std::string RunQuery(const std::string& query) { @@ -140,6 +139,7 @@ ArcAppTest& arc_test() { return arc_test_; } private: + base::SimpleTestClock clock_; std::unique_ptr<app_list::AppListModel> model_; std::unique_ptr<FakeAppListModelUpdater> model_updater_; std::unique_ptr<AppSearchProvider> app_search_;
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index d908c6b..b52dcf8 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -74,10 +74,9 @@ // Add search providers. controller->AddProvider( - apps_group_id, - std::make_unique<AppSearchProvider>( - profile, list_controller, std::make_unique<base::DefaultClock>(), - model_updater)); + apps_group_id, std::make_unique<AppSearchProvider>( + profile, list_controller, + base::DefaultClock::GetInstance(), model_updater)); controller->AddProvider(omnibox_group_id, std::make_unique<OmniboxProvider>( profile, list_controller)); if (arc::IsWebstoreSearchEnabled()) {
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc index fc08502f..1962e6e 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc
@@ -19,14 +19,13 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupOpenerTabHelper); // static -void PopupOpenerTabHelper::CreateForWebContents( - content::WebContents* contents, - std::unique_ptr<base::TickClock> tick_clock) { +void PopupOpenerTabHelper::CreateForWebContents(content::WebContents* contents, + base::TickClock* tick_clock) { DCHECK(contents); if (!FromWebContents(contents)) { - contents->SetUserData(UserDataKey(), - base::WrapUnique(new PopupOpenerTabHelper( - contents, std::move(tick_clock)))); + contents->SetUserData( + UserDataKey(), + base::WrapUnique(new PopupOpenerTabHelper(contents, tick_clock))); } } @@ -62,13 +61,11 @@ visible_time_before_tab_under_ = visibility_tracker_->GetForegroundDuration(); } -PopupOpenerTabHelper::PopupOpenerTabHelper( - content::WebContents* web_contents, - std::unique_ptr<base::TickClock> tick_clock) - : content::WebContentsObserver(web_contents), - tick_clock_(std::move(tick_clock)) { +PopupOpenerTabHelper::PopupOpenerTabHelper(content::WebContents* web_contents, + base::TickClock* tick_clock) + : content::WebContentsObserver(web_contents), tick_clock_(tick_clock) { visibility_tracker_ = std::make_unique<ScopedVisibilityTracker>( - tick_clock_.get(), + tick_clock_, web_contents->GetVisibility() != content::Visibility::HIDDEN); }
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h index 55ae85de..60f92c71 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.h
@@ -32,8 +32,11 @@ : public content::WebContentsObserver, public content::WebContentsUserData<PopupOpenerTabHelper> { public: + // |tick_clock| overrides the internal time for testing. This doesn't take the + // ownership of the clock. |tick_clock| must outlive the PopupOpenerTabHelper + // instance. static void CreateForWebContents(content::WebContents* contents, - std::unique_ptr<base::TickClock> tick_clock); + base::TickClock* tick_clock); ~PopupOpenerTabHelper() override; void OnOpenedPopup(PopupTracker* popup_tracker); @@ -55,7 +58,7 @@ friend class content::WebContentsUserData<PopupOpenerTabHelper>; PopupOpenerTabHelper(content::WebContents* web_contents, - std::unique_ptr<base::TickClock> tick_clock); + base::TickClock* tick_clock); // content::WebContentsObserver: void DidFinishNavigation( @@ -73,7 +76,7 @@ base::Optional<ukm::SourceId> last_committed_source_id_; // The clock which is used by the visibility trackers. - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; // Keeps track of the total foreground time for this tab. std::unique_ptr<ScopedVisibilityTracker> visibility_tracker_;
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc index 950cf7ba..74e06d7 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -59,10 +59,7 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - auto tick_clock = std::make_unique<base::SimpleTestTickClock>(); - raw_clock_ = tick_clock.get(); - PopupOpenerTabHelper::CreateForWebContents(web_contents(), - std::move(tick_clock)); + PopupOpenerTabHelper::CreateForWebContents(web_contents(), &raw_clock_); InfoBarService::CreateForWebContents(web_contents()); TabSpecificContentSettings::CreateForWebContents(web_contents()); #if !defined(OS_ANDROID) @@ -71,7 +68,7 @@ // The tick clock needs to be advanced manually so it isn't set to null, // which the code uses to determine if it is set yet. - raw_clock_->Advance(base::TimeDelta::FromMilliseconds(1)); + raw_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); } @@ -106,13 +103,13 @@ return raw_popup; } - base::SimpleTestTickClock* raw_clock() { return raw_clock_; } + base::SimpleTestTickClock* raw_clock() { return &raw_clock_; } base::HistogramTester* histogram_tester() { return &histogram_tester_; } private: base::HistogramTester histogram_tester_; - base::SimpleTestTickClock* raw_clock_ = nullptr; + base::SimpleTestTickClock raw_clock_; std::vector<std::unique_ptr<content::WebContents>> popups_;
diff --git a/chrome/browser/ui/blocked_content/popup_tracker.cc b/chrome/browser/ui/blocked_content/popup_tracker.cc index ba8ca1f71..bec6885 100644 --- a/chrome/browser/ui/blocked_content/popup_tracker.cc +++ b/chrome/browser/ui/blocked_content/popup_tracker.cc
@@ -34,8 +34,7 @@ PopupTracker::PopupTracker(content::WebContents* contents, content::WebContents* opener) - : content::WebContentsObserver(contents), - tick_clock_(std::make_unique<base::DefaultTickClock>()) { + : content::WebContentsObserver(contents) { if (auto* popup_opener = PopupOpenerTabHelper::FromWebContents(opener)) popup_opener->OnOpenedPopup(this); } @@ -51,7 +50,7 @@ // we've committed the first navigation in this WebContents. if (!first_load_visibility_tracker_) { first_load_visibility_tracker_ = std::make_unique<ScopedVisibilityTracker>( - tick_clock_.get(), + base::DefaultTickClock::GetInstance(), web_contents()->GetVisibility() != content::Visibility::HIDDEN); } else { web_contents()->RemoveUserData(UserDataKey()); @@ -69,4 +68,3 @@ first_load_visibility_tracker_->OnShown(); } } -
diff --git a/chrome/browser/ui/blocked_content/popup_tracker.h b/chrome/browser/ui/blocked_content/popup_tracker.h index 12abae81..8e5c09fb 100644 --- a/chrome/browser/ui/blocked_content/popup_tracker.h +++ b/chrome/browser/ui/blocked_content/popup_tracker.h
@@ -12,10 +12,6 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -namespace base { -class DefaultTickClock; -} - namespace content { class WebContents; } @@ -43,9 +39,6 @@ content::NavigationHandle* navigation_handle) override; void OnVisibilityChanged(content::Visibility visibility) override; - // The clock which is used by the visibility tracker. - std::unique_ptr<base::DefaultTickClock> tick_clock_; - // The |first_load_visibility_tracker_| tracks the time this WebContents is in // the foreground for the duration of the first page load. std::unique_ptr<ScopedVisibilityTracker> first_load_visibility_tracker_;
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm index 94b2e0b..5c60f35 100644 --- a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm +++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
@@ -184,13 +184,9 @@ } - (void)findPboardUpdated:(NSNotification*)notification { + [self clearFindResultsForCurrentBrowser]; if (!suppressPboardUpdateActions_) [self prepopulateText:[[FindPasteboard sharedInstance] findText]]; - [self clearFindResultsForCurrentBrowser]; - - BOOL buttonsEnabled = [[findText_ stringValue] length] > 0 ? YES : NO; - [previousButton_ setEnabled:buttonsEnabled]; - [nextButton_ setEnabled:buttonsEnabled]; } - (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth {
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm index e300a5d..02650e0 100644 --- a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm +++ b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
@@ -31,7 +31,7 @@ const SkColor kButtonHoverColor = SkColorSetARGB(20, 0, 0, 0); const SkColor kButtonPressedColor = SkColorSetARGB(31, 0, 0, 0); -const SkColor kAvatarIconColor = SkColorSetRGB(0x5a, 0x5a, 0x5a); +const SkColor kAvatarIconColor = SkColorSetRGB(0x75, 0x75, 0x75); const CGFloat kButtonHeight = 24;
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm index f470583..e648534 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
@@ -232,7 +232,7 @@ return themeIsDark ? SK_ColorWHITE : (provider && provider->ShouldIncreaseContrast() ? SK_ColorBLACK - : SkColorSetRGB(0x5A, 0x5A, 0x5A)); + : SkColorSetRGB(0x75, 0x75, 0x75)); } - (NSImage*)browserToolsIconForFillColor:(SkColor)fillColor {
diff --git a/chrome/browser/ui/extensions/hosted_app_menu_model.cc b/chrome/browser/ui/extensions/hosted_app_menu_model.cc index b19f6024..a684225 100644 --- a/chrome/browser/ui/extensions/hosted_app_menu_model.cc +++ b/chrome/browser/ui/extensions/hosted_app_menu_model.cc
@@ -22,7 +22,8 @@ HostedAppMenuModel::~HostedAppMenuModel() {} void HostedAppMenuModel::Build() { - CreateActionToolbarOverflowMenu(); + if (CreateActionToolbarOverflowMenu()) + AddSeparator(ui::UPPER_SEPARATOR); AddItemWithStringId(IDC_HOSTED_APP_MENU_APP_INFO, IDS_APP_CONTEXT_MENU_SHOW_INFO); int app_info_index = GetItemCount() - 1; @@ -38,13 +39,15 @@ AddSeparator(ui::NORMAL_SEPARATOR); AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL); AddItemWithStringId(IDC_OPEN_IN_CHROME, IDS_OPEN_IN_CHROME); + AddSeparator(ui::LOWER_SEPARATOR); CreateZoomMenu(); + AddSeparator(ui::UPPER_SEPARATOR); AddItemWithStringId(IDC_PRINT, IDS_PRINT); AddItemWithStringId(IDC_FIND, IDS_FIND); if (media_router::MediaRouterEnabled(browser()->profile())) AddItemWithStringId(IDC_ROUTE_MEDIA, IDS_MEDIA_ROUTER_MENU_ITEM_TITLE); + AddSeparator(ui::LOWER_SEPARATOR); CreateCutCopyPasteMenu(); - AddItemWithStringId(IDC_SITE_SETTINGS, IDS_SITE_SETTINGS); } void HostedAppMenuModel::LogMenuAction(AppMenuAction action_id) {
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 2587a034..b7f78fa 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -235,7 +235,7 @@ // ChromeSubresourceFilterClient being available in its constructor. PopupBlockerTabHelper::CreateForWebContents(web_contents); PopupOpenerTabHelper::CreateForWebContents( - web_contents, std::make_unique<base::DefaultTickClock>()); + web_contents, base::DefaultTickClock::GetInstance()); PrefsTabHelper::CreateForWebContents(web_contents); prerender::PrerenderTabHelper::CreateForWebContents(web_contents); PreviewsInfoBarTabHelper::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/tabs/tab_activity_simulator.cc b/chrome/browser/ui/tabs/tab_activity_simulator.cc index 2e18f28..af301cb 100644 --- a/chrome/browser/ui/tabs/tab_activity_simulator.cc +++ b/chrome/browser/ui/tabs/tab_activity_simulator.cc
@@ -49,9 +49,9 @@ std::unique_ptr<content::WebContents> TabActivitySimulator::CreateWebContents( content::BrowserContext* browser_context, - bool initially_hidden) { + bool initially_visible) { content::WebContents::CreateParams params(browser_context, nullptr); - params.initially_hidden = initially_hidden; + params.initially_hidden = !initially_visible; std::unique_ptr<content::WebContents> test_contents( content::WebContentsTester::CreateTestWebContents(params)); @@ -66,11 +66,13 @@ TabStripModel* tab_strip_model, const GURL& initial_url, ui::PageTransition page_transition) { - // Create as a background tab if there are other tabs in the tab strip. - bool initially_hidden = tab_strip_model->count() > 0; + // Create as a foreground tab if it's the only tab in the tab strip. + bool initially_visible = tab_strip_model->empty(); content::WebContents* test_contents = - CreateWebContents(tab_strip_model->profile(), initially_hidden).release(); - tab_strip_model->AppendWebContents(test_contents, false); + CreateWebContents(tab_strip_model->profile(), initially_visible) + .release(); + tab_strip_model->AppendWebContents(test_contents, + initially_visible /* foreground */); Navigate(test_contents, initial_url, page_transition); return test_contents; }
diff --git a/chrome/browser/ui/tabs/tab_activity_simulator.h b/chrome/browser/ui/tabs/tab_activity_simulator.h index 0f14678..1fde371 100644 --- a/chrome/browser/ui/tabs/tab_activity_simulator.h +++ b/chrome/browser/ui/tabs/tab_activity_simulator.h
@@ -36,7 +36,7 @@ // Creates a new WebContents suitable for testing. std::unique_ptr<content::WebContents> CreateWebContents( content::BrowserContext* browser_context, - bool initially_hidden = true); + bool initially_visible = false); // Creates a new WebContents suitable for testing, adds it to the tab strip // and commits a navigation to |initial_url|. The WebContents is owned by the
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index de46c514..1da3c0e 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -723,7 +723,8 @@ // - Learn about the browser and global customisation e.g. settings, help. // - Browser relaunch, quit. void AppMenuModel::Build() { - CreateActionToolbarOverflowMenu(); + if (CreateActionToolbarOverflowMenu()) + AddSeparator(ui::UPPER_SEPARATOR); AddItem(IDC_VIEW_INCOMPATIBILITIES, l10n_util::GetStringUTF16(IDS_VIEW_INCOMPATIBILITIES)); @@ -756,7 +757,9 @@ bookmark_sub_menu_model_.get()); } + AddSeparator(ui::LOWER_SEPARATOR); CreateZoomMenu(); + AddSeparator(ui::UPPER_SEPARATOR); AddItemWithStringId(IDC_PRINT, IDS_PRINT); if (media_router::MediaRouterEnabled(browser()->profile())) @@ -774,9 +777,9 @@ tools_menu_model_.reset(new ToolsMenuModel(this, browser_)); AddSubMenuWithStringId( IDC_MORE_TOOLS_MENU, IDS_MORE_TOOLS_MENU, tools_menu_model_.get()); - // Append the full menu including separators. The final separator only gets - // appended when this is a touch menu - otherwise it would get added twice. + AddSeparator(ui::LOWER_SEPARATOR); CreateCutCopyPasteMenu(); + AddSeparator(ui::UPPER_SEPARATOR); AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS); // The help submenu is only displayed on official Chrome builds. As the @@ -803,7 +806,7 @@ uma_action_recorded_ = false; } -void AppMenuModel::CreateActionToolbarOverflowMenu() { +bool AppMenuModel::CreateActionToolbarOverflowMenu() { // We only add the extensions overflow container if there are any icons that // aren't shown in the main container. // browser_->window() can return null during startup, and @@ -819,13 +822,12 @@ AddItem(kEmptyMenuItemCommand, base::string16()); #endif AddItem(IDC_EXTENSIONS_OVERFLOW_MENU, base::string16()); - AddSeparator(ui::UPPER_SEPARATOR); + return true; } + return false; } void AppMenuModel::CreateCutCopyPasteMenu() { - AddSeparator(ui::LOWER_SEPARATOR); - // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the // layout for this menu item in AppMenu.xib. It does, however, use the // command_id value from AddButtonItem() to identify this special item. @@ -834,14 +836,9 @@ edit_menu_item_model_->AddGroupItemWithStringId(IDC_COPY, IDS_COPY); edit_menu_item_model_->AddGroupItemWithStringId(IDC_PASTE, IDS_PASTE); AddButtonItem(IDC_EDIT_MENU, edit_menu_item_model_.get()); - - AddSeparator(ui::UPPER_SEPARATOR); } void AppMenuModel::CreateZoomMenu() { - // This menu needs to be enclosed by separators. - AddSeparator(ui::LOWER_SEPARATOR); - // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the // layout for this menu item in AppMenu.xib. It does, however, use the // command_id value from AddButtonItem() to identify this special item. @@ -854,8 +851,6 @@ zoom_menu_item_model_->AddItemWithImage(IDC_FULLSCREEN, IDR_FULLSCREEN_MENU_BUTTON); AddButtonItem(IDC_ZOOM_MENU, zoom_menu_item_model_.get()); - - AddSeparator(ui::UPPER_SEPARATOR); } void AppMenuModel::UpdateZoomControls() {
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h index 209fa4b..85bccd4 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.h +++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -167,15 +167,14 @@ // Builds the menu model, adding appropriate menu items. virtual void Build(); - // Appends everything needed for the clipboard menu: a menu break, the - // clipboard menu content and the finalizing menu break. + // Appends a clipboard menu (without separators). void CreateCutCopyPasteMenu(); - // Add a menu item for the browser action icons. - void CreateActionToolbarOverflowMenu(); + // Add a menu item for the browser action icons if there is overflow, returns + // whether the menu was added. + bool CreateActionToolbarOverflowMenu(); - // Appends everything needed for the zoom menu: a menu break, then the zoom - // menu content and then another menu break. + // Appends a zoom menu (without separators). void CreateZoomMenu(); private:
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc index d542f62..00e129d 100644 --- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc +++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -5,14 +5,18 @@ #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h" #include "chrome/browser/ui/content_settings/content_setting_image_model.h" +#include "chrome/browser/ui/extensions/hosted_app_browser_controller.h" #include "chrome/browser/ui/extensions/hosted_app_menu_model.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h" #include "chrome/browser/ui/views/toolbar/app_menu.h" #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" @@ -46,6 +50,14 @@ : views::MenuButton(base::string16(), this, false), browser_view_(browser_view) { SetInkDropMode(InkDropMode::ON); + // This name is guaranteed not to change during the lifetime of this button. + // Get the app name only, aka "Google Docs" instead of "My Doc - Google Docs", + // because the menu applies to the entire app. + base::string16 app_name = base::UTF8ToUTF16( + browser_view->browser()->hosted_app_controller()->GetAppShortName()); + SetAccessibleName(app_name); + SetTooltipText( + l10n_util::GetStringFUTF16(IDS_HOSTED_APPMENU_TOOLTIP, app_name)); } HostedAppButtonContainer::AppMenuButton::~AppMenuButton() {}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 6c71920..c56d5709 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -547,7 +547,10 @@ end += offset; } - SetTextAndSelectedRange(full_url, gfx::Range(start, end)); + // Update the text to the full unelided URL. The caret is positioned at 0, as + // otherwise we will spuriously scroll the text to the end of the new string. + SetWindowTextAndCaretPos(full_url, 0, false, false); + SelectRange(gfx::Range(start, end)); return true; }
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc index c1a17d96..7850680 100644 --- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc +++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
@@ -94,7 +94,9 @@ void RoundedOmniboxResultsFrame::OnBeforeWidgetInit( views::Widget::InitParams* params) { params->shadow_type = views::Widget::InitParams::SHADOW_TYPE_DROP; + params->corner_radius = GetLayoutConstant(LOCATION_BAR_BUBBLE_CORNER_RADIUS); params->shadow_elevation = kElevation; + params->name = "RoundedOmniboxResultsFrameWindow"; } // static @@ -128,25 +130,5 @@ #if defined(USE_AURA) GetWidget()->GetNativeWindow()->SetEventTargeter( std::make_unique<ResultsTargeter>(content_insets_.top())); - - // This works well on ChromeOS. On other platforms, some tricks may be needed - // to ensure the shadow is not clipped to the parent Widget bounds, since it - // can peek outside the browser bounds. It is possible to just put the shadow - // layer into the Widget's layer hierarchy, but that needs further logic to - // ensure mouse events pass through it to the browser below. - auto* shadow_layer = - wm::ShadowController::GetShadowForWindow(GetWidget()->GetNativeWindow()); -#if defined(OS_WIN) - // To get a shadow from the ShadowController on Windows, the Widget can not be - // top-level (it must be a child within another DesktopWindowTreeHost). - // ChromeViewsDelegate decides this: it chooses top-level because software - // compositing is force-enabled for the Widget on windows, and because - // top-level Widgets are preferred under Aero (compositing window manager). - if (!shadow_layer) - return; -#endif - DCHECK(shadow_layer); - shadow_layer->SetRoundedCornerRadius( - GetLayoutConstant(LOCATION_BAR_BUBBLE_CORNER_RADIUS)); #endif }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index c959618b..b9ed3d1 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -964,7 +964,11 @@ HoverButton* profile_card = new HoverButton( this, std::move(current_profile_photo), hover_button_title, show_email ? avatar_item.username : base::string16()); - if (show_email) + // TODO(crbug.com/815047): Sometimes, |avatar_item.username| is empty when + // |show_email| is true, which should never happen. This causes a crash when + // setting the elision behavior, so until this bug is fixed, avoid the crash + // by checking that the username is not empty. + if (show_email && !avatar_item.username.empty()) profile_card->SetSubtitleElideBehavior(gfx::ELIDE_EMAIL); current_profile_card_ = profile_card; view->AddChildView(current_profile_card_);
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc index 713d4b8..dd89803 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -548,3 +548,10 @@ ASSERT_NO_FATAL_FAILURE(OpenProfileChooserView(browser())); EXPECT_EQ(GetDiceSigninPromoShowCount(), 11); } + +// Verify there is no crash when the chooser is used to display a signed-in +// profile with an empty username. +IN_PROC_BROWSER_TEST_F(ProfileChooserViewExtensionsTest, SignedInNoUsername) { + AddAccountToProfile(browser()->profile(), ""); + OpenProfileChooserView(browser()); +}
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 66f7beb..e6d81a04 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -1217,7 +1217,8 @@ const SkColor title_color = theme_provider->GetColor(IsActive() ? ThemeProperties::COLOR_TAB_TEXT : ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); - const SkColor new_button_color = SkColorSetA(title_color, 0xA0); + // Alpha here is chosen so that black on tab is 0x75 (kChromeIconGrey). + const SkColor new_button_color = SkColorSetA(title_color, 0x84); if (button_color_ != new_button_color) { button_color_ = new_button_color; title_->SetEnabledColor(title_color);
diff --git a/chrome/browser/ui/webui/browsing_history_handler.cc b/chrome/browser/ui/webui/browsing_history_handler.cc index 1c32288..da08cc4 100644 --- a/chrome/browser/ui/webui/browsing_history_handler.cc +++ b/chrome/browser/ui/webui/browsing_history_handler.cc
@@ -230,7 +230,8 @@ } // namespace BrowsingHistoryHandler::BrowsingHistoryHandler() - : clock_(new base::DefaultClock()), browsing_history_service_(nullptr) {} + : clock_(base::DefaultClock::GetInstance()), + browsing_history_service_(nullptr) {} BrowsingHistoryHandler::~BrowsingHistoryHandler() {} @@ -366,9 +367,8 @@ // Convert the result vector into a ListValue. base::ListValue results_value; for (const BrowsingHistoryService::HistoryEntry& entry : results) { - std::unique_ptr<base::Value> value( - HistoryEntryToValue(entry, bookmark_model, supervised_user_service, - sync_service, clock_.get())); + std::unique_ptr<base::Value> value(HistoryEntryToValue( + entry, bookmark_model, supervised_user_service, sync_service, clock_)); results_value.Append(std::move(value)); }
diff --git a/chrome/browser/ui/webui/browsing_history_handler.h b/chrome/browser/ui/webui/browsing_history_handler.h index 0a30097..eef6585 100644 --- a/chrome/browser/ui/webui/browsing_history_handler.h +++ b/chrome/browser/ui/webui/browsing_history_handler.h
@@ -59,10 +59,9 @@ // ProfileBasedBrowsingHistoryDriver implementation. Profile* GetProfile() override; - // For tests. - void set_clock(std::unique_ptr<base::Clock> clock) { - clock_ = std::move(clock); - } + // For tests. This does not take the ownership of the clock. |clock| must + // outlive the BrowsingHistoryHandler instance. + void set_clock(base::Clock* clock) { clock_ = clock; } private: FRIEND_TEST_ALL_PREFIXES(BrowsingHistoryHandlerTest, @@ -70,7 +69,7 @@ FRIEND_TEST_ALL_PREFIXES(BrowsingHistoryHandlerTest, MdTruncatesTitles); // The clock used to vend times. - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; std::unique_ptr<history::BrowsingHistoryService> browsing_history_service_;
diff --git a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc index 49a2467..fb5013e 100644 --- a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc +++ b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
@@ -82,17 +82,16 @@ class BrowsingHistoryHandlerWithWebUIForTesting : public BrowsingHistoryHandler { public: - explicit BrowsingHistoryHandlerWithWebUIForTesting(content::WebUI* web_ui) - : test_clock_(new base::SimpleTestClock()) { - set_clock(base::WrapUnique(test_clock_)); + explicit BrowsingHistoryHandlerWithWebUIForTesting(content::WebUI* web_ui) { + set_clock(&test_clock_); set_web_ui(web_ui); - test_clock_->SetNow(PretendNow()); + test_clock_.SetNow(PretendNow()); } - base::SimpleTestClock* test_clock() { return test_clock_; } + base::SimpleTestClock* test_clock() { return &test_clock_; } private: - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; }; } // namespace
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc index 3623c03..3f3a9c1 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -255,7 +255,7 @@ EncryptionMigrationScreenHandler::EncryptionMigrationScreenHandler() : BaseScreenHandler(kScreenId), - tick_clock_(std::make_unique<base::DefaultTickClock>()), + tick_clock_(base::DefaultTickClock::GetInstance()), weak_ptr_factory_(this) { set_call_js_prefix(kJsScreenPath); free_disk_space_fetcher_ = base::Bind(&base::SysInfo::AmountOfFreeDiskSpace, @@ -386,8 +386,8 @@ } void EncryptionMigrationScreenHandler::SetTickClockForTesting( - std::unique_ptr<base::TickClock> tick_clock) { - tick_clock_ = std::move(tick_clock); + base::TickClock* tick_clock) { + tick_clock_ = tick_clock; } void EncryptionMigrationScreenHandler::RegisterMessages() {
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h index 5c3d34d..48ce6f48 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
@@ -64,7 +64,9 @@ FreeDiskSpaceFetcher free_disk_space_fetcher); // Testing only: Sets the tick clock used to measure elapsed time during // migration. - void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock); + // This doesn't toke the ownership of the clock. |tick_clock| must outlive the + // EncryptionMigrationScreenHandler instance. + void SetTickClockForTesting(base::TickClock* tick_clock); virtual device::mojom::WakeLock* GetWakeLock(); @@ -180,7 +182,7 @@ std::unique_ptr<LoginFeedback> login_feedback_; // Used to measure elapsed time during migration. - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; FreeDiskSpaceFetcher free_disk_space_fetcher_;
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc index 36a602c..1e60a10 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc
@@ -69,9 +69,7 @@ SetFreeDiskSpaceFetcherForTesting(base::BindRepeating( &TestEncryptionMigrationScreenHandler::FreeDiskSpaceFetcher, base::Unretained(this))); - auto tick_clock = std::make_unique<base::SimpleTestTickClock>(); - testing_tick_clock_ = tick_clock.get(); - SetTickClockForTesting(std::move(tick_clock)); + SetTickClockForTesting(&testing_tick_clock_); } // Sets the testing WebUI. @@ -87,7 +85,7 @@ // Returns the SimpleTestTickClock used to simulate time elapsed during // migration. base::SimpleTestTickClock* testing_tick_clock() { - return testing_tick_clock_; + return &testing_tick_clock_; } FakeWakeLock* fake_wake_lock() { return &fake_wake_lock_; } @@ -102,9 +100,8 @@ FakeWakeLock fake_wake_lock_; - // Non-owned pointer. Tick clock used to simulate time elapsed during - // migration. This is actually owned by the base class. - base::SimpleTestTickClock* testing_tick_clock_; + // Tick clock used to simulate time elapsed during migration. + base::SimpleTestTickClock testing_tick_clock_; int64_t free_disk_space_; };
diff --git a/chrome/browser/ui/webui/help/version_updater.h b/chrome/browser/ui/webui/help/version_updater.h index bbf32c3..2bfc0d5 100644 --- a/chrome/browser/ui/webui/help/version_updater.h +++ b/chrome/browser/ui/webui/help/version_updater.h
@@ -48,7 +48,7 @@ // types. #if defined(OS_CHROMEOS) typedef base::Callback<void(const std::string&)> ChannelCallback; - typedef base::Callback<void(update_engine::EndOfLifeStatus status)> + typedef base::OnceCallback<void(update_engine::EndOfLifeStatus status)> EolStatusCallback; #endif @@ -91,7 +91,7 @@ bool is_powerwash_allowed) = 0; virtual void GetChannel(bool get_current_channel, const ChannelCallback& callback) = 0; - virtual void GetEolStatus(const EolStatusCallback& callback) = 0; + virtual void GetEolStatus(EolStatusCallback callback) = 0; // Sets a one time permission on a certain update in Update Engine. // - update_version: the Chrome OS version we want to update to.
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc index 3658855..815a49e 100644 --- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc +++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -243,19 +243,20 @@ cb.Run(current_channel); } -void VersionUpdaterCros::GetEolStatus(const EolStatusCallback& cb) { +void VersionUpdaterCros::GetEolStatus(EolStatusCallback cb) { UpdateEngineClient* update_engine_client = DBusThreadManager::Get()->GetUpdateEngineClient(); // Request the Eol Status. Bind to a weak_ptr bound method rather than passing // |cb| directly so that |cb| does not outlive |this|. - update_engine_client->GetEolStatus(base::Bind( - &VersionUpdaterCros::OnGetEolStatus, weak_ptr_factory_.GetWeakPtr(), cb)); + update_engine_client->GetEolStatus( + base::BindOnce(&VersionUpdaterCros::OnGetEolStatus, + weak_ptr_factory_.GetWeakPtr(), std::move(cb))); } -void VersionUpdaterCros::OnGetEolStatus(const EolStatusCallback& cb, +void VersionUpdaterCros::OnGetEolStatus(EolStatusCallback cb, update_engine::EndOfLifeStatus status) { - cb.Run(status); + std::move(cb).Run(status); } VersionUpdaterCros::VersionUpdaterCros(content::WebContents* web_contents)
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.h b/chrome/browser/ui/webui/help/version_updater_chromeos.h index 7defbfa5..ec6ea7d 100644 --- a/chrome/browser/ui/webui/help/version_updater_chromeos.h +++ b/chrome/browser/ui/webui/help/version_updater_chromeos.h
@@ -33,7 +33,7 @@ // Gets the last update status, without triggering a new check or download. void GetUpdateStatus(const StatusCallback& callback); - void GetEolStatus(const EolStatusCallback& callback) override; + void GetEolStatus(EolStatusCallback callback) override; protected: friend class VersionUpdater; @@ -58,7 +58,7 @@ const std::string& current_channel); // Callback from UpdateEngineClient::GetEolStatus(). - void OnGetEolStatus(const EolStatusCallback& cb, + void OnGetEolStatus(EolStatusCallback cb, update_engine::EndOfLifeStatus status); // BrowserContext in which the class was instantiated.
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc index 188ad72..0e22bfc 100644 --- a/chrome/browser/ui/webui/settings/about_handler.cc +++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -335,6 +335,10 @@ html_source->AddString("aboutUserAgent", GetUserAgent()); html_source->AddString("aboutJsEngineVersion", V8_VERSION_STRING); html_source->AddString("aboutBlinkVersion", content::GetWebKitVersion()); + html_source->AddString("endOfLifeMessage", + l10n_util::GetStringUTF16(IDS_EOL_NOTIFICATION_EOL)); + html_source->AddString("endOfLifeLearnMoreURL", + base::ASCIIToUTF16(chrome::kEolNotificationURL)); #endif return new AboutHandler(); @@ -378,6 +382,10 @@ "refreshTPMFirmwareUpdateStatus", base::Bind(&AboutHandler::HandleRefreshTPMFirmwareUpdateStatus, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getHasEndOfLife", + base::BindRepeating(&AboutHandler::HandleGetHasEndOfLife, + base::Unretained(this))); #endif #if defined(OS_MACOSX) web_ui()->RegisterMessageCallback( @@ -603,6 +611,25 @@ event->SetBoolean("updateAvailable", update_available); FireWebUIListener("tpm-firmware-update-status-changed", *event); } + +void AboutHandler::HandleGetHasEndOfLife(const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + version_updater_->GetEolStatus( + base::BindOnce(&AboutHandler::OnGetEndOfLifeStatus, + weak_factory_.GetWeakPtr(), callback_id)); +} + +void AboutHandler::OnGetEndOfLifeStatus(std::string callback_id, + update_engine::EndOfLifeStatus status) { + // Check for EndOfLifeStatus::kEol only because + // EndOfLifeStatus::kSecurityOnly state is no longer supported. + ResolveJavascriptCallback( + base::Value(callback_id), + base::Value(status == update_engine::EndOfLifeStatus::kEol)); +} + #endif // defined(OS_CHROMEOS) void AboutHandler::RequestUpdate() {
diff --git a/chrome/browser/ui/webui/settings/about_handler.h b/chrome/browser/ui/webui/settings/about_handler.h index 3127e97..0e47e25 100644 --- a/chrome/browser/ui/webui/settings/about_handler.h +++ b/chrome/browser/ui/webui/settings/about_handler.h
@@ -147,6 +147,16 @@ void OnRegulatoryLabelTextRead(std::string callback_id, const base::FilePath& label_dir_path, const std::string& text); + + // Retrieves device end of life status. + // Will asynchronously resolve the provided callback with a boolean + // indicating whether the device has reached end-of-life status (will no + // longer receive updates). + void HandleGetHasEndOfLife(const base::ListValue* args); + + // Callbacks for version_updater_->GetEolStatus calls. + void OnGetEndOfLifeStatus(std::string callback_id, + update_engine::EndOfLifeStatus status); #endif // Specialized instance of the VersionUpdater used to update the browser.
diff --git a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc new file mode 100644 index 0000000..ff89c5a --- /dev/null +++ b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
@@ -0,0 +1,102 @@ +// 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/settings/incompatible_applications_handler_win.h" + +#include <string> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/values.h" +#include "chrome/browser/conflicts/problematic_programs_updater_win.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace settings { + +IncompatibleApplicationsHandler::IncompatibleApplicationsHandler() = default; + +IncompatibleApplicationsHandler::~IncompatibleApplicationsHandler() = default; + +void IncompatibleApplicationsHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "requestIncompatibleApplicationsList", + base::BindRepeating(&IncompatibleApplicationsHandler:: + HandleRequestIncompatibleApplicationsList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "startProgramUninstallation", + base::BindRepeating( + &IncompatibleApplicationsHandler::HandleStartProgramUninstallation, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getSubtitlePluralString", + base::BindRepeating( + &IncompatibleApplicationsHandler::HandleGetSubtitlePluralString, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getSubtitleNoAdminRightsPluralString", + base::BindRepeating(&IncompatibleApplicationsHandler:: + HandleGetSubtitleNoAdminRightsPluralString, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getListTitlePluralString", + base::BindRepeating( + &IncompatibleApplicationsHandler::HandleGetListTitlePluralString, + base::Unretained(this))); +} + +void IncompatibleApplicationsHandler::HandleRequestIncompatibleApplicationsList( + const base::ListValue* args) { + CHECK_EQ(1u, args->GetList().size()); + CHECK(ProblematicProgramsUpdater::HasCachedPrograms()); + + AllowJavascript(); + + const base::Value& callback_id = args->GetList().front(); + ResolveJavascriptCallback(callback_id, + ProblematicProgramsUpdater::GetCachedPrograms()); +} + +void IncompatibleApplicationsHandler::HandleStartProgramUninstallation( + const base::ListValue* args) { + CHECK_EQ(1u, args->GetList().size()); + + // TODO(pmonette): Open the Apps & Settings page with the program name + // highlighted. +} + +void IncompatibleApplicationsHandler::HandleGetSubtitlePluralString( + const base::ListValue* args) { + GetPluralString(IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE, + args); +} + +void IncompatibleApplicationsHandler:: + HandleGetSubtitleNoAdminRightsPluralString(const base::ListValue* args) { + GetPluralString( + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE_NO_ADMIN_RIGHTS, + args); +} + +void IncompatibleApplicationsHandler::HandleGetListTitlePluralString( + const base::ListValue* args) { + GetPluralString(IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_LIST_TITLE, args); +} + +void IncompatibleApplicationsHandler::GetPluralString( + int id, + const base::ListValue* args) { + CHECK_EQ(2U, args->GetList().size()); + + const base::Value& callback_id = args->GetList()[0]; + int num_applications = args->GetList()[1].GetInt(); + DCHECK_GT(0, num_applications); + + ResolveJavascriptCallback( + callback_id, + base::Value(l10n_util::GetPluralStringFUTF16(id, num_applications))); +} + +} // namespace settings
diff --git a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h new file mode 100644 index 0000000..0c4c27f --- /dev/null +++ b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
@@ -0,0 +1,45 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_INCOMPATIBLE_APPLICATIONS_HANDLER_WIN_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_INCOMPATIBLE_APPLICATIONS_HANDLER_WIN_H_ + +#include "base/macros.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" + +namespace base { +class ListValue; +} + +namespace settings { + +// Incompatible Applications settings page UI handler. +class IncompatibleApplicationsHandler : public SettingsPageUIHandler { + public: + IncompatibleApplicationsHandler(); + ~IncompatibleApplicationsHandler() override; + + // SettingsPageUIHandler: + void RegisterMessages() override; + void OnJavascriptAllowed() override {} + void OnJavascriptDisallowed() override {} + + private: + // Sends the list of incompatible applications to the caller via a promise. + void HandleRequestIncompatibleApplicationsList(const base::ListValue* args); + + // Initiates the uninstallation of the program passed using |args|. + void HandleStartProgramUninstallation(const base::ListValue* args); + + void HandleGetSubtitlePluralString(const base::ListValue* args); + void HandleGetSubtitleNoAdminRightsPluralString(const base::ListValue* args); + void HandleGetListTitlePluralString(const base::ListValue* args); + void GetPluralString(int id, const base::ListValue* args); + + DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsHandler); +}; + +} // namespace settings + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_INCOMPATIBLE_APPLICATIONS_HANDLER_WIN_H_
diff --git a/chrome/browser/ui/webui/settings/incompatible_software_handler_win.cc b/chrome/browser/ui/webui/settings/incompatible_software_handler_win.cc deleted file mode 100644 index 09754e6..0000000 --- a/chrome/browser/ui/webui/settings/incompatible_software_handler_win.cc +++ /dev/null
@@ -1,55 +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 "chrome/browser/ui/webui/settings/incompatible_software_handler_win.h" - -#include <string> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/values.h" -#include "chrome/browser/conflicts/problematic_programs_updater_win.h" -#include "chrome/grit/generated_resources.h" -#include "ui/base/l10n/l10n_util.h" - -namespace settings { - -IncompatibleSoftwareHandler::IncompatibleSoftwareHandler() = default; - -IncompatibleSoftwareHandler::~IncompatibleSoftwareHandler() = default; - -void IncompatibleSoftwareHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback( - "requestIncompatibleSoftwareList", - base::BindRepeating( - &IncompatibleSoftwareHandler::HandleRequestIncompatibleSoftwareList, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "startProgramUninstallation", - base::BindRepeating( - &IncompatibleSoftwareHandler::HandleStartProgramUninstallation, - base::Unretained(this))); -} - -void IncompatibleSoftwareHandler::HandleRequestIncompatibleSoftwareList( - const base::ListValue* args) { - CHECK_EQ(1u, args->GetList().size()); - CHECK(ProblematicProgramsUpdater::HasCachedPrograms()); - - AllowJavascript(); - - const base::Value& callback_id = args->GetList().front(); - ResolveJavascriptCallback(callback_id, - ProblematicProgramsUpdater::GetCachedPrograms()); -} - -void IncompatibleSoftwareHandler::HandleStartProgramUninstallation( - const base::ListValue* args) { - CHECK_EQ(1u, args->GetList().size()); - - // TODO(pmonette): Open the Apps & Settings page with the program name - // highlighted. -} - -} // namespace settings
diff --git a/chrome/browser/ui/webui/settings/incompatible_software_handler_win.h b/chrome/browser/ui/webui/settings/incompatible_software_handler_win.h deleted file mode 100644 index 656a9aa0..0000000 --- a/chrome/browser/ui/webui/settings/incompatible_software_handler_win.h +++ /dev/null
@@ -1,40 +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 CHROME_BROWSER_UI_WEBUI_SETTINGS_INCOMPATIBLE_SOFTWARE_HANDLER_WIN_H_ -#define CHROME_BROWSER_UI_WEBUI_SETTINGS_INCOMPATIBLE_SOFTWARE_HANDLER_WIN_H_ - -#include "base/macros.h" -#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" - -namespace base { -class ListValue; -} - -namespace settings { - -// Incompatible Software settings page UI handler. -class IncompatibleSoftwareHandler : public SettingsPageUIHandler { - public: - IncompatibleSoftwareHandler(); - ~IncompatibleSoftwareHandler() override; - - // SettingsPageUIHandler: - void RegisterMessages() override; - void OnJavascriptAllowed() override {} - void OnJavascriptDisallowed() override {} - - private: - // Sends the list of incompatible software to the caller via a promise. - void HandleRequestIncompatibleSoftwareList(const base::ListValue* args); - - // Initiates the uninstallation of the program passed using |args|. - void HandleStartProgramUninstallation(const base::ListValue* args); - - DISALLOW_COPY_AND_ASSIGN(IncompatibleSoftwareHandler); -}; - -} // namespace settings - -#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_INCOMPATIBLE_SOFTWARE_HANDLER_WIN_H_
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index a3dc57c..9bd60b8 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -867,29 +867,31 @@ cleanup_details_explanation); } -void AddIncompatibleSoftwareStrings(content::WebUIDataSource* html_source) { +void AddIncompatibleApplicationsStrings(content::WebUIDataSource* html_source) { LocalizedString localized_strings[] = { - {"incompatibleSoftwareResetCardTitle", - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_RESET_CARD_TITLE}, - {"incompatibleSoftwareSubpageSubtitle", - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_SUBPAGE_SUBTITLE}, - {"incompatibleSoftwareSubpageSubtitleNoAdminRights", - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_SUBPAGE_SUBTITLE_NO_ADMIN_RIGHTS}, - {"incompatibleSoftwareListTitle", - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_LIST_TITLE}, - {"incompatibleSoftwareRemoveButton", - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_REMOVE_BUTTON}, - {"incompatibleSoftwareUpdateButton", - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_UPDATE_BUTTON}, - {"incompatibleSoftwareDone", IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_DONE}, + {"incompatibleApplicationsResetCardTitle", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_RESET_CARD_TITLE}, + {"incompatibleApplicationsSubpageSubtitle", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE}, + {"incompatibleApplicationsSubpageSubtitleNoAdminRights", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_SUBTITLE_NO_ADMIN_RIGHTS}, + {"incompatibleApplicationsListTitle", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_LIST_TITLE}, + {"incompatibleApplicationsRemoveButton", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_REMOVE_BUTTON}, + {"incompatibleApplicationsUpdateButton", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_UPDATE_BUTTON}, + {"incompatibleApplicationsDone", + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_DONE}, }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); // TODO(pmonette): Add the help URL when available. base::string16 learn_how_text = l10n_util::GetStringFUTF16( - IDS_SETTINGS_INCOMPATIBLE_SOFTWARE_SUBPAGE_LEARN_HOW, + IDS_SETTINGS_INCOMPATIBLE_APPLICATIONS_SUBPAGE_LEARN_HOW, base::ASCIIToUTF16("chrome://placeholder")); - html_source->AddString("incompatibleSoftwareSubpageLearnHow", learn_how_text); + html_source->AddString("incompatibleApplicationsSubpageLearnHow", + learn_how_text); } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) @@ -2311,7 +2313,7 @@ #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) AddChromeCleanupStrings(html_source); - AddIncompatibleSoftwareStrings(html_source); + AddIncompatibleApplicationsStrings(html_source); #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) AddChangePasswordStrings(html_source);
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index 2914877..401fc7f 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -55,7 +55,7 @@ #include "chrome/browser/ui/webui/settings/chrome_cleanup_handler.h" #if defined(GOOGLE_CHROME_BUILD) #include "chrome/browser/conflicts/problematic_programs_updater_win.h" -#include "chrome/browser/ui/webui/settings/incompatible_software_handler_win.h" +#include "chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h" #include "chrome/grit/chrome_unscaled_resources.h" #endif #endif // defined(OS_WIN) @@ -229,15 +229,16 @@ #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) ProblematicProgramsUpdater::TrimCache(); - bool has_incompatible_software = + bool has_incompatible_applications = ProblematicProgramsUpdater::HasCachedPrograms(); - html_source->AddBoolean("showIncompatibleSoftware", - has_incompatible_software); + html_source->AddBoolean("showIncompatibleApplications", + has_incompatible_applications); // TODO(pmonette): Implement a function to determine hasAdminRights. - html_source->AddBoolean("hasAdminRights", false); + html_source->AddBoolean("hasAdminRights", true); - if (has_incompatible_software) - AddSettingsPageUIHandler(base::MakeUnique<IncompatibleSoftwareHandler>()); + if (has_incompatible_applications) + AddSettingsPageUIHandler( + base::MakeUnique<IncompatibleApplicationsHandler>()); #endif // OS_WIN && defined(GOOGLE_CHROME_BUILD) bool password_protection_available = false;
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 3d39647f..4c239727 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -186,7 +186,7 @@ // Enables a site-wide permission in the UI which controls access to the // asynchronous Clipboard web API. const base::Feature kClipboardContentSetting{"ClipboardContentSetting", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #if defined(OS_CHROMEOS) // Enable project Crostini, Linux VMs on Chrome OS. @@ -204,6 +204,10 @@ const base::Feature kDesktopPWAWindowing{"DesktopPWAWindowing", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables or disables Desktop PWAs capturing links. +const base::Feature kDesktopPWAsLinkCapturing{ + "DesktopPWAsLinkCapturing", base::FEATURE_DISABLED_BY_DEFAULT}; + #if !defined(OS_ANDROID) const base::Feature kDoodlesOnLocalNtp{"DoodlesOnLocalNtp", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -458,6 +462,11 @@ const base::Feature kPermissionsBlacklist{ "PermissionsBlacklist", base::FEATURE_DISABLED_BY_DEFAULT}; +// Delegate permissions to cross-origin iframes when the feature has been +// allowed by feature policy. +const base::Feature kPermissionDelegation{"PermissionDelegation", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Disables PostScript generation when printing to PostScript capable printers // and instead sends Emf files. #if defined(OS_WIN)
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 193b1b66..1ce51fb 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -108,6 +108,8 @@ extern const base::Feature kDesktopPWAWindowing; +extern const base::Feature kDesktopPWAsLinkCapturing; + #if !defined(OS_ANDROID) extern const base::Feature kDoodlesOnLocalNtp; #endif @@ -241,6 +243,8 @@ extern const base::Feature kPermissionsBlacklist; +extern const base::Feature kPermissionDelegation; + #if defined(OS_WIN) extern const base::Feature kDisablePostScriptPrinting; #endif
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index ad9080e..9195d54 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -617,6 +617,7 @@ "../browser/pdf/pdf_extension_test.cc", "../browser/pdf/pdf_extension_test_util.cc", "../browser/pdf/pdf_extension_test_util.h", + "../browser/permissions/permission_delegation_browsertest.cc", "../browser/permissions/permission_request_manager_browsertest.cc", "../browser/permissions/permissions_browsertest.cc", "../browser/permissions/permissions_browsertest.h",
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc index aecc2345..004914a 100644 --- a/chrome/test/base/ui_test_utils.cc +++ b/chrome/test/base/ui_test_utils.cc
@@ -63,6 +63,7 @@ #include "content/public/test/test_utils.h" #include "device/geolocation/geolocation_provider.h" #include "net/base/filename_util.h" +#include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store.h" @@ -402,10 +403,10 @@ namespace { -void GetCookiesCallback(base::WaitableEvent* event, - std::string* cookies, - const std::string& cookie_line) { - *cookies = cookie_line; +void GetCookieListCallback(base::WaitableEvent* event, + net::CookieList* cookies, + const net::CookieList& cookie_list) { + *cookies = cookie_list; event->Signal(); } @@ -413,11 +414,12 @@ const GURL& url, const scoped_refptr<net::URLRequestContextGetter>& context_getter, base::WaitableEvent* event, - std::string* cookies) { - context_getter->GetURLRequestContext()->cookie_store()-> - GetCookiesWithOptionsAsync( + net::CookieList* cookie_list) { + context_getter->GetURLRequestContext() + ->cookie_store() + ->GetCookieListWithOptionsAsync( url, net::CookieOptions(), - base::Bind(&GetCookiesCallback, event, cookies)); + base::BindOnce(&GetCookieListCallback, event, cookie_list)); } } // namespace @@ -435,11 +437,14 @@ ->GetURLRequestContext(); base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); + net::CookieList cookie_list; CHECK(content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&GetCookiesOnIOThread, url, context_getter, &event, value))); + base::BindOnce(&GetCookiesOnIOThread, url, context_getter, &event, + &cookie_list))); event.Wait(); + *value = net::CanonicalCookie::BuildCookieLine(cookie_list); *value_size = static_cast<int>(value->size()); } }
diff --git a/chrome/test/data/printing/content_with_same_site_iframe.html b/chrome/test/data/printing/content_with_same_site_iframe.html new file mode 100644 index 0000000..f11e5b7c --- /dev/null +++ b/chrome/test/data/printing/content_with_same_site_iframe.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> + <head> + <title>Test printing isolated iframe</title> + <head> + <body> + <p> + This is a test page. + </p> + <div> + <iframe src="/printing/test1.html" id="iframe" style="height:150px; margin:0px; padding:0px"> + </iframe> + </div> + </body> +</html>
diff --git a/chrome/test/data/two_iframes_blank.html b/chrome/test/data/two_iframes_blank.html new file mode 100644 index 0000000..5b9928a --- /dev/null +++ b/chrome/test/data/two_iframes_blank.html
@@ -0,0 +1,7 @@ +<html> +<body> +<iframe id="iframe1" name="iframe1"></iframe> +<iframe id="iframe2" name="iframe2"></iframe> +</body> +</html> +
diff --git a/chrome/test/data/webui/settings/about_page_tests.js b/chrome/test/data/webui/settings/about_page_tests.js index ede8dbc6..d90ca932 100644 --- a/chrome/test/data/webui/settings/about_page_tests.js +++ b/chrome/test/data/webui/settings/about_page_tests.js
@@ -15,11 +15,8 @@ if (cr.isChromeOS) { methodNames.push( - 'getChannelInfo', - 'getVersionInfo', - 'getRegulatoryInfo', - 'refreshTPMFirmwareUpdateStatus', - 'setChannel'); + 'getChannelInfo', 'getVersionInfo', 'getRegulatoryInfo', + 'getHasEndOfLife', 'refreshTPMFirmwareUpdateStatus', 'setChannel'); } if (cr.isMac) @@ -52,6 +49,9 @@ this.tpmFirmwareUpdateStatus_ = { updateAvailable: false, }; + + /** @private {boolean} */ + this.hasEndOfLife_ = false; } } @@ -129,6 +129,12 @@ this.regulatoryInfo_ = regulatoryInfo; }; + /** @param {boolean} hasEndOfLife */ + TestAboutPageBrowserProxy.prototype.setHasEndOfLife = function( + hasEndOfLife) { + this.hasEndOfLife_ = hasEndOfLife; + }; + /** @override */ TestAboutPageBrowserProxy.prototype.getChannelInfo = function() { this.methodCalled('getChannelInfo'); @@ -148,6 +154,12 @@ }; /** @override */ + TestAboutPageBrowserProxy.prototype.getHasEndOfLife = function() { + this.methodCalled('getHasEndOfLife'); + return Promise.resolve(this.hasEndOfLife_); + }; + + /** @override */ TestAboutPageBrowserProxy.prototype.setChannel = function( channel, isPowerwashAllowed) { this.methodCalled('setChannel', [channel, isPowerwashAllowed]); @@ -302,85 +314,83 @@ assertTrue(!!page.$$('#updateStatusMessage a[hidden]')); }); - /** - * Test that when the current platform has been marked as deprecated (but - * not end of the line) a deprecation warning message is displayed, - * without interfering with the update status message and icon. - */ - test('ObsoleteSystem', function() { - loadTimeData.overrideValues({ - aboutObsoleteNowOrSoon: true, - aboutObsoleteEndOfTheLine: false, + if (!cr.isChromeOS) { + /** + * Test that when the current platform has been marked as deprecated + * (but not end of the line) a deprecation warning message is displayed, + * without interfering with the update status message and icon. + */ + test('ObsoleteSystem', function() { + loadTimeData.overrideValues({ + aboutObsoleteNowOrSoon: true, + aboutObsoleteEndOfTheLine: false, + }); + + return initNewPage().then(function() { + const icon = page.$$('iron-icon'); + assertTrue(!!icon); + assertTrue(!!page.$.updateStatusMessage); + assertTrue(!!page.$.deprecationWarning); + assertFalse(page.$.deprecationWarning.hidden); + + fireStatusChanged(UpdateStatus.CHECKING); + assertEquals(SPINNER_ICON, icon.src); + assertEquals(null, icon.getAttribute('icon')); + assertFalse(page.$.deprecationWarning.hidden); + assertFalse(page.$.updateStatusMessage.hidden); + + fireStatusChanged(UpdateStatus.UPDATING); + assertEquals(SPINNER_ICON, icon.src); + assertEquals(null, icon.getAttribute('icon')); + assertFalse(page.$.deprecationWarning.hidden); + assertFalse(page.$.updateStatusMessage.hidden); + + fireStatusChanged(UpdateStatus.NEARLY_UPDATED); + assertEquals(null, icon.src); + assertEquals('settings:check-circle', icon.icon); + assertFalse(page.$.deprecationWarning.hidden); + assertFalse(page.$.updateStatusMessage.hidden); + }); }); - return initNewPage().then(function() { - const icon = page.$$('iron-icon'); - assertTrue(!!icon); - assertTrue(!!page.$.updateStatusMessage); - assertTrue(!!page.$.deprecationWarning); + /** + * Test that when the current platform has reached the end of the line, + * a deprecation warning message and an error icon is displayed. + */ + test('ObsoleteSystemEndOfLine', function() { + loadTimeData.overrideValues({ + aboutObsoleteNowOrSoon: true, + aboutObsoleteEndOfTheLine: true, + }); + return initNewPage().then(function() { + const icon = page.$$('iron-icon'); + assertTrue(!!icon); + assertTrue(!!page.$.deprecationWarning); + assertTrue(!!page.$.updateStatusMessage); - assertFalse(page.$.deprecationWarning.hidden); - // Update status message should be hidden before user has checked for - // updates, on ChromeOS. - assertEquals(cr.isChromeOS, page.$.updateStatusMessage.hidden); + assertFalse(page.$.deprecationWarning.hidden); + assertFalse(page.$.deprecationWarning.hidden); - fireStatusChanged(UpdateStatus.CHECKING); - assertEquals(SPINNER_ICON, icon.src); - assertEquals(null, icon.getAttribute('icon')); - assertFalse(page.$.deprecationWarning.hidden); - assertFalse(page.$.updateStatusMessage.hidden); + fireStatusChanged(UpdateStatus.CHECKING); + assertEquals(null, icon.src); + assertEquals('settings:error', icon.icon); + assertFalse(page.$.deprecationWarning.hidden); + assertTrue(page.$.updateStatusMessage.hidden); - fireStatusChanged(UpdateStatus.UPDATING); - assertEquals(SPINNER_ICON, icon.src); - assertEquals(null, icon.getAttribute('icon')); - assertFalse(page.$.deprecationWarning.hidden); - assertFalse(page.$.updateStatusMessage.hidden); + fireStatusChanged(UpdateStatus.FAILED); + assertEquals(null, icon.src); + assertEquals('settings:error', icon.icon); + assertFalse(page.$.deprecationWarning.hidden); + assertTrue(page.$.updateStatusMessage.hidden); - fireStatusChanged(UpdateStatus.NEARLY_UPDATED); - assertEquals(null, icon.src); - assertEquals('settings:check-circle', icon.icon); - assertFalse(page.$.deprecationWarning.hidden); - assertFalse(page.$.updateStatusMessage.hidden); + fireStatusChanged(UpdateStatus.UPDATED); + assertEquals(null, icon.src); + assertEquals('settings:error', icon.icon); + assertFalse(page.$.deprecationWarning.hidden); + assertTrue(page.$.updateStatusMessage.hidden); + }); }); - }); - - /** - * Test that when the current platform has reached the end of the line, a - * deprecation warning message and an error icon is displayed. - */ - test('ObsoleteSystemEndOfLine', function() { - loadTimeData.overrideValues({ - aboutObsoleteNowOrSoon: true, - aboutObsoleteEndOfTheLine: true, - }); - return initNewPage().then(function() { - const icon = page.$$('iron-icon'); - assertTrue(!!icon); - assertTrue(!!page.$.deprecationWarning); - assertTrue(!!page.$.updateStatusMessage); - - assertFalse(page.$.deprecationWarning.hidden); - assertFalse(page.$.deprecationWarning.hidden); - - fireStatusChanged(UpdateStatus.CHECKING); - assertEquals(null, icon.src); - assertEquals('settings:error', icon.icon); - assertFalse(page.$.deprecationWarning.hidden); - assertTrue(page.$.updateStatusMessage.hidden); - - fireStatusChanged(UpdateStatus.FAILED); - assertEquals(null, icon.src); - assertEquals('settings:error', icon.icon); - assertFalse(page.$.deprecationWarning.hidden); - assertTrue(page.$.updateStatusMessage.hidden); - - fireStatusChanged(UpdateStatus.UPDATED); - assertEquals(null, icon.src); - assertEquals('settings:error', icon.icon); - assertFalse(page.$.deprecationWarning.hidden); - assertTrue(page.$.updateStatusMessage.hidden); - }); - }); + } test('Relaunch', function() { let relaunch = page.$.relaunch; @@ -598,6 +608,51 @@ }); }); }); + + test('DeviceEndOfLife', function() { + /** + * Checks the visibility of the end of life message and icon. + * @param {boolean} isShowing Whether the end of life UI is expected + * to be visible. + * @return {!Promise} + */ + function checkHasEndOfLife(isShowing) { + return aboutBrowserProxy.whenCalled('getHasEndOfLife') + .then(function() { + const endOfLifeMessageContainer = + page.$.endOfLifeMessageContainer; + assertTrue(!!endOfLifeMessageContainer); + assertEquals(isShowing, !endOfLifeMessageContainer.hidden); + + // Update status message should be hidden before user has + // checked for updates. + assertTrue(page.$.updateStatusMessage.hidden); + + fireStatusChanged(UpdateStatus.CHECKING); + assertEquals(isShowing, page.$.updateStatusMessage.hidden); + + if (isShowing) { + const icon = page.$$('iron-icon'); + assertTrue(!!icon); + assertEquals(null, icon.src); + assertEquals('settings:end-of-life', icon.icon); + + const checkForUpdates = page.$.checkForUpdates; + assertTrue(!!checkForUpdates); + assertTrue(checkForUpdates.hidden); + } + }); + } + + return checkHasEndOfLife(false) + .then(function() { + aboutBrowserProxy.setHasEndOfLife(true); + return initNewPage(); + }) + .then(function() { + return checkHasEndOfLife(true); + }); + }); } if (!cr.isChromeOS) {
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 56d6906..53312a4 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -612,23 +612,23 @@ * @constructor * @extends {CrSettingsBrowserTest} */ -function CrSettingsIncompatibleSoftwarePageTest() {} +function CrSettingsIncompatibleApplicationsPageTest() {} -CrSettingsIncompatibleSoftwarePageTest.prototype = { +CrSettingsIncompatibleApplicationsPageTest.prototype = { __proto__: CrSettingsBrowserTest.prototype, /** @override */ browsePreload: - 'chrome://settings/incompatible_software_page/incompatible_software_page.html', + 'chrome://settings/incompatible_applications_page/incompatible_applications_page.html', /** @override */ extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ '../test_browser_proxy.js', - 'incompatible_software_page_test.js', + 'incompatible_applications_page_test.js', ]), }; -TEST_F('CrSettingsIncompatibleSoftwarePageTest', 'All', function() { +TEST_F('CrSettingsIncompatibleApplicationsPageTest', 'All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/settings/incompatible_applications_page_test.js b/chrome/test/data/webui/settings/incompatible_applications_page_test.js new file mode 100644 index 0000000..25bb1d1 --- /dev/null +++ b/chrome/test/data/webui/settings/incompatible_applications_page_test.js
@@ -0,0 +1,229 @@ +// 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. + +/** @implements {settings.IncompatibleApplicationsBrowserProxy} */ +class TestIncompatibleApplicationsBrowserProxy extends TestBrowserProxy { + constructor() { + super([ + 'requestIncompatibleApplicationsList', + 'startProgramUninstallation', + 'openURL', + 'getSubtitlePluralString', + 'getSubtitleNoAdminRightsPluralString', + 'getListTitlePluralString', + ]); + + /** @private {!Array<!settings.IncompatibleApplication>} */ + this.incompatibleApplications_ = []; + } + + /** @override */ + requestIncompatibleApplicationsList() { + this.methodCalled('requestIncompatibleApplicationsList'); + return Promise.resolve(this.incompatibleApplications_); + } + + /** @override */ + startProgramUninstallation(programName) { + this.methodCalled('startProgramUninstallation', programName); + } + + /** @override */ + openURL(url) { + this.methodCalled('openURL', url); + } + + /** @override */ + getSubtitlePluralString(numApplications) { + this.methodCalled('getSubtitlePluralString'); + return Promise.resolve(''); + } + + /** @override */ + getSubtitleNoAdminRightsPluralString(numApplications) { + this.methodCalled('getSubtitleNoAdminRightsPluralString'); + return Promise.resolve(''); + } + + /** @override */ + getListTitlePluralString(numApplications) { + this.methodCalled('getListTitlePluralString'); + return Promise.resolve(''); + } + + /** + * Sets the list of incompatible applications returned by + * requestIncompatibleApplicationsList(). + * @param {!Array<!settings.IncompatibleApplication>} incompatibleApplications + */ + setIncompatibleApplications(incompatibleApplications) { + this.incompatibleApplications_ = incompatibleApplications; + } +} + +suite('incompatibleApplicationsHandler', function() { + let incompatibleApplicationsPage = null; + + /** @type {?TestIncompatibleApplicationsBrowserProxy} */ + let incompatibleApplicationsBrowserProxy = null; + + const incompatibleApplication1 = { + 'name': 'Application 1', + 'type': 0, + 'url': '', + }; + const incompatibleApplication2 = { + 'name': 'Application 2', + 'type': 0, + 'url': '', + }; + const incompatibleApplication3 = { + 'name': 'Application 3', + 'type': 0, + 'url': '', + }; + const learnMoreIncompatibleApplication = { + 'name': 'Update Application', + 'type': 1, + 'url': 'chrome://update-url', + }; + const updateIncompatibleApplication = { + 'name': 'Update Application', + 'type': 1, + 'url': 'chrome://update-url', + }; + + /** + * @param {!Array<settings.IncompatibleApplication>} + */ + function validateList(incompatibleApplications) { + const list = incompatibleApplicationsPage.shadowRoot.querySelectorAll( + '.incompatible-application:not([hidden])'); + + assertEquals(list.length, incompatibleApplications.length); + } + + setup(function() { + incompatibleApplicationsBrowserProxy = + new TestIncompatibleApplicationsBrowserProxy(); + settings.IncompatibleApplicationsBrowserProxyImpl.instance_ = + incompatibleApplicationsBrowserProxy; + }); + + /** + * @param {boolean} hasAdminRights + * @return {!Promise} + */ + function initPage(hasAdminRights) { + incompatibleApplicationsBrowserProxy.reset(); + PolymerTest.clearBody(); + + loadTimeData.overrideValues({ + hasAdminRights: hasAdminRights, + }); + + incompatibleApplicationsPage = + document.createElement('settings-incompatible-applications-page'); + document.body.appendChild(incompatibleApplicationsPage); + return incompatibleApplicationsBrowserProxy + .whenCalled('requestIncompatibleApplicationsList') + .then(function() { + Polymer.dom.flush(); + }); + } + + test('openMultipleIncompatibleApplications', function() { + const multipleIncompatibleApplicationsTestList = [ + incompatibleApplication1, + incompatibleApplication2, + incompatibleApplication3, + ]; + + incompatibleApplicationsBrowserProxy.setIncompatibleApplications( + multipleIncompatibleApplicationsTestList); + + return initPage(true).then(function() { + validateList(multipleIncompatibleApplicationsTestList); + }); + }); + + test('startProgramUninstallation', function() { + const singleIncompatibleApplicationTestList = [ + incompatibleApplication1, + ]; + + incompatibleApplicationsBrowserProxy.setIncompatibleApplications( + singleIncompatibleApplicationTestList); + + return initPage(true /* hasAdminRights */) + .then(function() { + validateList(singleIncompatibleApplicationTestList); + + // Retrieve the incompatible-application-item and tap it. It should be + // visible. + let item = incompatibleApplicationsPage.$$( + '.incompatible-application:not([hidden])'); + item.$$('.primary-button').click(); + + return incompatibleApplicationsBrowserProxy.whenCalled( + 'startProgramUninstallation'); + }) + .then(function(programName) { + assertEquals(incompatibleApplication1.name, programName); + }); + }); + + test('learnMore', function() { + const singleUpdateIncompatibleApplicationTestList = [ + learnMoreIncompatibleApplication, + ]; + + incompatibleApplicationsBrowserProxy.setIncompatibleApplications( + singleUpdateIncompatibleApplicationTestList); + + return initPage(true /* hasAdminRights */) + .then(function() { + validateList(singleUpdateIncompatibleApplicationTestList); + + // Retrieve the incompatible-application-item and tap it. It should be + // visible. + let item = incompatibleApplicationsPage.$$( + '.incompatible-application:not([hidden])'); + item.$$('.primary-button').click(); + + return incompatibleApplicationsBrowserProxy.whenCalled('openURL'); + }) + .then(function(url) { + assertEquals(updateIncompatibleApplication.url, url); + }); + }); + + test('noAdminRights', function() { + const eachTypeIncompatibleApplicationsTestList = [ + incompatibleApplication1, + learnMoreIncompatibleApplication, + updateIncompatibleApplication, + ]; + + incompatibleApplicationsBrowserProxy.setIncompatibleApplications( + eachTypeIncompatibleApplicationsTestList); + + return initPage(false /* hasAdminRights */).then(function() { + validateList(eachTypeIncompatibleApplicationsTestList); + + let items = incompatibleApplicationsPage.shadowRoot.querySelectorAll( + '.incompatible-application:not([hidden])'); + + assertEquals(items.length, 3); + + items.forEach(function(item, index) { + // Just the name of the incompatible application is displayed inside a + // div node. The <incompatible-application-item> component is not used. + item.textContent.includes( + eachTypeIncompatibleApplicationsTestList[index].name); + assertNotEquals(item.nodeName, 'INCOMPATIBLE-APPLICATION-ITEM'); + }); + }); + }); +});
diff --git a/chrome/test/data/webui/settings/incompatible_software_page_test.js b/chrome/test/data/webui/settings/incompatible_software_page_test.js deleted file mode 100644 index b7482ab..0000000 --- a/chrome/test/data/webui/settings/incompatible_software_page_test.js +++ /dev/null
@@ -1,207 +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. - -/** @implements {settings.IncompatibleSoftwareBrowserProxy} */ -class TestIncompatibleSoftwareBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'requestIncompatibleSoftwareList', - 'startProgramUninstallation', - 'openURL', - ]); - - /** @private {!Array<!settings.IncompatibleSoftware>} */ - this.incompatibleSoftware_ = []; - } - - /** @override */ - requestIncompatibleSoftware() { - this.methodCalled('requestIncompatibleSoftware'); - return Promise.resolve(this.incompatibleSoftware_); - } - - /** @override */ - startProgramUninstallation(programName) { - this.methodCalled('startProgramUninstallation', programName); - } - - /** @override */ - openURL(url) { - this.methodCalled('openURL', url); - } - - /** - * Sets the list of incompatible software returned by - * requestIncompatibleSoftwareList(). - * @param {!Array<!settings.IncompatibleSoftware>} incompatibleSoftware - */ - setIncompatibleSoftware(incompatibleSoftware) { - this.incompatibleSoftware_ = incompatibleSoftware; - } -} - -suite('incompatibleSoftwareHandler', function() { - let incompatibleSoftwarePage = null; - - /** @type {?TestIncompatibleSoftwareBrowserProxy} */ - let incompatibleSoftwareBrowserProxy = null; - - const incompatibleSoftware1 = { - 'name': 'Application 1', - 'type': 0, - 'url': '', - }; - const incompatibleSoftware2 = { - 'name': 'Application 2', - 'type': 0, - 'url': '', - }; - const incompatibleSoftware3 = { - 'name': 'Application 3', - 'type': 0, - 'url': '', - }; - const learnMoreIncompatibleSoftware = { - 'name': 'Update Application', - 'type': 1, - 'url': 'chrome://update-url', - }; - const updateIncompatibleSoftware = { - 'name': 'Update Application', - 'type': 1, - 'url': 'chrome://update-url', - }; - - /** - * @param {!Array<settings.IncompatibleSoftware>} - */ - function validateList(incompatibleSoftware) { - const list = incompatibleSoftwarePage.shadowRoot.querySelectorAll( - '.incompatible-software:not([hidden])'); - - assertEquals(list.length, incompatibleSoftware.length); - } - - setup(function() { - incompatibleSoftwareBrowserProxy = new TestIncompatibleSoftwareBrowserProxy(); - settings.incompatibleSoftwareBrowserProxyImpl.instance_ = - incompatibleSoftwareBrowserProxy; - }); - - /** - * @param {boolean} hasAdminRights - * @return {!Promise} - */ - function initPage(hasAdminRights) { - incompatibleSoftwareBrowserProxy.reset(); - PolymerTest.clearBody(); - - loadTimeData.overrideValues({ - hasAdminRights: hasAdminRights, - }); - - incompatibleSoftwarePage = - document.createElement('settings-incompatible-software-page'); - document.body.appendChild(incompatibleSoftwarePage); - return incompatibleSoftwareBrowserProxy - .whenCalled('requestIncompatibleSoftwareList') - .then(function() { - Polymer.dom.flush(); - }); - } - - test('openMultipleIncompatibleSoftware', function() { - const multipleIncompatibleSoftwareTestList = [ - incompatibleSoftware1, - incompatibleSoftware2, - incompatibleSoftware3, - ]; - - incompatibleSoftwareBrowserProxy.setIncompatibleSoftware( - multipleIncompatibleSoftwareTestList); - - return initPage(true).then(function() { - validateList(multipleIncompatibleSoftwareTestList); - }); - }); - - test('startProgramUninstallation', function() { - const singleIncompatibleSoftwareTestList = [ - incompatibleSoftware1, - ]; - - incompatibleSoftwareBrowserProxy.setIncompatibleSoftware( - singleIncompatibleSoftwareTestList); - - return initPage(true /* hasAdminRights */) - .then(function() { - validateList(singleIncompatibleSoftwareTestList); - - // Retrieve the incompatible-software-item and tap it. It should be - // visible. - let item = - incompatibleSoftwarePage.$$('.incompatible-software:not([hidden])'); - item.$$('.primary-button').click(); - - return incompatibleSoftwareBrowserProxy.whenCalled( - 'startProgramUninstallation'); - }) - .then(function(programName) { - assertEquals(incompatibleSoftware1.name, programName); - }); - }); - - test('learnMore', function() { - const singleUpdateIncompatibleSoftwareTestList = [ - learnMoreIncompatibleSoftware, - ]; - - incompatibleSoftwareBrowserProxy.setIncompatibleSoftware( - singleUpdateIncompatibleSoftwareTestList); - - return initPage(true /* hasAdminRights */) - .then(function() { - validateList(singleUpdateIncompatibleSoftwareTestList); - - // Retrieve the incompatible-software-item and tap it. It should be - // visible. - let item = - incompatibleSoftwarePage.$$('.incompatible-software:not([hidden])'); - item.$$('.primary-button').click(); - - return incompatibleSoftwareBrowserProxy.whenCalled('openURL'); - }) - .then(function(url) { - assertEquals(updateIncompatibleSoftware.url, url); - }); - }); - - test('noAdminRights', function() { - const eachTypeIncompatibleSoftwareTestList = [ - incompatibleSoftware1, - learnMoreIncompatibleSoftware, - updateIncompatibleSoftware, - ]; - - incompatibleSoftwareBrowserProxy.setIncompatibleSoftware( - eachTypeIncompatibleSoftwareTestList); - - return initPage(false /* hasAdminRights */).then(function() { - validateList(eachTypeIncompatibleSoftwareTestList); - - let items = incompatibleSoftwarePage.shadowRoot.querySelectorAll( - '.incompatible-software:not([hidden])'); - - assertEquals(items.length, 3); - - items.forEach(function(item, index) { - // Just the name of the incompatible software is displayed inside a div - // node. The <incompatible-software-item> component is not used. - item.textContent.includes( - eachTypeIncompatibleSoftwareTestList[index].name); - assertNotEquals(item.nodeName, 'INCOMPATIBLE-SOFTWARE-ITEM'); - }); - }); - }); -});
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index 23ef0c7..5daa3fd4 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -106,7 +106,9 @@ namespace { #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA) -int kSignalsToRunClosure[] = { SIGTERM, SIGINT, }; +int kSignalsToRunClosure[] = { + SIGTERM, SIGINT, +}; // Closure to run on SIGTERM and SIGINT. base::Closure* g_signal_closure = nullptr; base::PlatformThreadId g_main_thread_id; @@ -551,8 +553,7 @@ // Initializing metrics service and network delegates must happen after cast // service is intialized because CastMetricsServiceClient and // CastNetworkDelegate may use components initialized by cast service. - cast_browser_process_->metrics_service_client() - ->Initialize(cast_browser_process_->cast_service()); + cast_browser_process_->metrics_service_client()->Initialize(); url_request_context_factory_->InitializeNetworkDelegates(); cast_browser_process_->cast_service()->Start();
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.cc b/chromecast/browser/metrics/cast_metrics_service_client.cc index 002a901..f0224f0 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.cc +++ b/chromecast/browser/metrics/cast_metrics_service_client.cc
@@ -275,7 +275,6 @@ PrefService* pref_service, net::URLRequestContextGetter* request_context) : pref_service_(pref_service), - cast_service_(nullptr), client_info_loaded_(false), #if defined(OS_LINUX) external_metrics_(nullptr), @@ -314,11 +313,8 @@ force_client_id_ = client_id; } -void CastMetricsServiceClient::Initialize(CastService* cast_service) { - DCHECK(cast_service); - DCHECK(!cast_service_); - cast_service_ = cast_service; - +void CastMetricsServiceClient::Initialize() { + DCHECK(!metrics_state_manager_); metrics_state_manager_ = ::metrics::MetricsStateManager::Create( pref_service_, this, base::string16(), base::Bind(&CastMetricsServiceClient::StoreClientInfo,
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.h b/chromecast/browser/metrics/cast_metrics_service_client.h index cf00abc..8d0d0d6 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.h +++ b/chromecast/browser/metrics/cast_metrics_service_client.h
@@ -35,9 +35,6 @@ } // namespace net namespace chromecast { - -class CastService; - namespace metrics { class ExternalMetrics; @@ -61,7 +58,7 @@ // thread. void ProcessExternalEvents(const base::Closure& cb); - void Initialize(CastService* cast_service); + void Initialize(); void Finalize(); // ::metrics::MetricsServiceClient: @@ -96,7 +93,6 @@ void StoreClientInfo(const ::metrics::ClientInfo& client_info); PrefService* const pref_service_; - CastService* cast_service_; std::string client_id_; std::string force_client_id_; bool client_info_loaded_;
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 5285461..68a3f6d 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -10442.0.0 \ No newline at end of file +10445.0.0 \ No newline at end of file
diff --git a/chromeos/components/tether/ble_connection_manager.cc b/chromeos/components/tether/ble_connection_manager.cc index a9f7445..925d00b 100644 --- a/chromeos/components/tether/ble_connection_manager.cc +++ b/chromeos/components/tether/ble_connection_manager.cc
@@ -147,6 +147,11 @@ return secure_channel_->SendMessage(std::string(kTetherFeature), payload); } +void BleConnectionManager::ConnectionMetadata::Disconnect() { + DCHECK(HasSecureChannel()); + secure_channel_->Disconnect(); +} + void BleConnectionManager::ConnectionMetadata::OnSecureChannelStatusChanged( cryptauth::SecureChannel* secure_channel, const cryptauth::SecureChannel::Status& old_status, @@ -222,7 +227,7 @@ ble_scanner_(ble_scanner), ad_hoc_ble_advertisement_(ad_hoc_ble_advertisement), timer_factory_(std::make_unique<TimerFactory>()), - clock_(std::make_unique<base::DefaultClock>()), + clock_(base::DefaultClock::GetInstance()), has_registered_observer_(false), weak_ptr_factory_(this) {} @@ -272,24 +277,22 @@ connection_metadata->UnregisterConnectionReason(connection_reason); if (!connection_metadata->HasReasonForConnection()) { - // Use a copy of the device ID. It's possible that the device ID passed to - // this function will be destroyed due to fields being manipulated below. - const std::string device_id_copy = device_id; + if (connection_metadata->HasEstablishedConnection()) { + connection_metadata->Disconnect(); + } else { + // |device_id| references memory that will be deleted below; make a copy. + const std::string device_id_copy = device_id; + cryptauth::SecureChannel::Status status_before_erase = + connection_metadata->GetStatus(); + device_id_to_metadata_map_.erase(device_id_copy); - cryptauth::SecureChannel::Status status_before_disconnect = - connection_metadata->GetStatus(); - device_id_to_metadata_map_.erase(device_id_copy); - if (status_before_disconnect == - cryptauth::SecureChannel::Status::CONNECTING) { - StopConnectionAttemptAndMoveToEndOfQueue(device_id_copy); - } - if (status_before_disconnect != - cryptauth::SecureChannel::Status::DISCONNECTED) { - // Send a status update for the disconnection. - NotifySecureChannelStatusChanged( - device_id_copy, status_before_disconnect, - cryptauth::SecureChannel::Status::DISCONNECTED, - StateChangeDetail::STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED); + if (status_before_erase == cryptauth::SecureChannel::Status::CONNECTING) { + StopConnectionAttemptAndMoveToEndOfQueue(device_id_copy); + NotifySecureChannelStatusChanged( + device_id_copy, cryptauth::SecureChannel::Status::CONNECTING, + cryptauth::SecureChannel::Status::DISCONNECTED, + StateChangeDetail::STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED); + } } } @@ -539,8 +542,24 @@ const cryptauth::SecureChannel::Status& old_status, const cryptauth::SecureChannel::Status& new_status, StateChangeDetail state_change_detail) { - NotifySecureChannelStatusChanged(device_id, old_status, new_status, - state_change_detail); + ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id); + DCHECK(connection_metadata); + + // Create copies of the references passed to this function. If the map entry + // is erased below, the references will point to deleted memory. + const std::string device_id_copy = device_id; + const cryptauth::SecureChannel::Status old_status_copy = old_status; + const cryptauth::SecureChannel::Status new_status_copy = new_status; + + if (!connection_metadata->HasReasonForConnection() && + new_status == cryptauth::SecureChannel::Status::DISCONNECTED) { + device_id_to_metadata_map_.erase(device_id_copy); + state_change_detail = + StateChangeDetail::STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED; + } + + NotifySecureChannelStatusChanged(device_id_copy, old_status_copy, + new_status_copy, state_change_detail); UpdateConnectionAttempts(); } @@ -595,9 +614,9 @@ } void BleConnectionManager::SetTestDoubles( - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, std::unique_ptr<TimerFactory> test_timer_factory) { - clock_ = std::move(test_clock); + clock_ = test_clock; timer_factory_ = std::move(test_timer_factory); }
diff --git a/chromeos/components/tether/ble_connection_manager.h b/chromeos/components/tether/ble_connection_manager.h index 6c786288..5e19fe2fe 100644 --- a/chromeos/components/tether/ble_connection_manager.h +++ b/chromeos/components/tether/ble_connection_manager.h
@@ -176,6 +176,7 @@ void SetSecureChannel( std::unique_ptr<cryptauth::SecureChannel> secure_channel); int SendMessage(const std::string& payload); + void Disconnect(); // cryptauth::SecureChannel::Observer: void OnSecureChannelStatusChanged( @@ -222,7 +223,7 @@ StateChangeDetail state_change_detail); void OnGattCharacteristicsNotAvailable(const std::string& device_id); - void SetTestDoubles(std::unique_ptr<base::Clock> test_clock, + void SetTestDoubles(base::Clock* test_clock, std::unique_ptr<TimerFactory> test_timer_factory); // Record various operation durations. These need to be separate methods @@ -239,7 +240,7 @@ AdHocBleAdvertiser* ad_hoc_ble_advertisement_; std::unique_ptr<TimerFactory> timer_factory_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; bool has_registered_observer_; std::map<std::string, std::unique_ptr<ConnectionMetadata>>
diff --git a/chromeos/components/tether/ble_connection_manager_unittest.cc b/chromeos/components/tether/ble_connection_manager_unittest.cc index 2efaf92..45808b1 100644 --- a/chromeos/components/tether/ble_connection_manager_unittest.cc +++ b/chromeos/components/tether/ble_connection_manager_unittest.cc
@@ -187,10 +187,8 @@ EXPECT_EQ(expected_adapter_, adapter); EXPECT_EQ(expected_remote_service_uuid_, remote_service_uuid); EXPECT_FALSE(should_set_low_connection_latency); - - return base::WrapUnique<FakeConnectionWithAddress>( - new FakeConnectionWithAddress(remote_device, - bluetooth_device->GetAddress())); + return base::WrapUnique(new FakeConnectionWithAddress( + remote_device, bluetooth_device->GetAddress())); } private: @@ -236,6 +234,10 @@ public: FakeSecureChannelFactory() = default; + std::vector<FakeSecureChannel*>& created_channels() { + return created_channels_; + } + void SetExpectedDeviceAddress(const std::string& expected_device_address) { expected_device_address_ = expected_device_address; } @@ -246,12 +248,15 @@ FakeConnectionWithAddress* fake_connection = static_cast<FakeConnectionWithAddress*>(connection.get()); EXPECT_EQ(expected_device_address_, fake_connection->GetDeviceAddress()); - return base::WrapUnique( - new FakeSecureChannel(std::move(connection), cryptauth_service)); + FakeSecureChannel* channel = + new FakeSecureChannel(std::move(connection), cryptauth_service); + created_channels_.push_back(channel); + return base::WrapUnique(channel); } private: std::string expected_device_address_; + std::vector<FakeSecureChannel*> created_channels_; }; BleConnectionManagerTest() : test_devices_(CreateTestDevices(4)) { @@ -296,10 +301,9 @@ test_observer_ = base::WrapUnique(new TestObserver()); manager_->AddObserver(test_observer_.get()); - test_clock_ = new base::SimpleTestClock(); - test_clock_->SetNow(base::Time::UnixEpoch()); + test_clock_.SetNow(base::Time::UnixEpoch()); mock_timer_factory_ = new MockTimerFactory(); - manager_->SetTestDoubles(base::WrapUnique(test_clock_), + manager_->SetTestDoubles(&test_clock_, base::WrapUnique(mock_timer_factory_)); } @@ -423,7 +427,8 @@ void VerifyDeviceNotRegistered(const cryptauth::RemoteDevice& remote_device) { BleConnectionManager::ConnectionMetadata* connection_metadata = manager_->GetConnectionMetadata(remote_device.GetDeviceId()); - EXPECT_FALSE(connection_metadata); + if (connection_metadata) + EXPECT_FALSE(connection_metadata->HasReasonForConnection()); } // Registers |remote_device|, creates a connection to that device at @@ -432,7 +437,7 @@ const cryptauth::RemoteDevice& remote_device, const std::string& bluetooth_address, const ConnectionReason connection_reason) { - test_clock_->SetNow(base::Time::UnixEpoch()); + test_clock_.SetNow(base::Time::UnixEpoch()); manager_->RegisterRemoteDevice(remote_device.GetDeviceId(), connection_reason); @@ -472,16 +477,16 @@ num_expected_authenticated_channels_++; - test_clock_->SetNow(base::Time::UnixEpoch()); + test_clock_.SetNow(base::Time::UnixEpoch()); channel->ChangeStatus(cryptauth::SecureChannel::Status::CONNECTING); - test_clock_->Advance(kStatusConnectedTime); + test_clock_.Advance(kStatusConnectedTime); channel->ChangeStatus(cryptauth::SecureChannel::Status::CONNECTED); histogram_tester_.ExpectTimeBucketCount( "InstantTethering.Performance.AdvertisementToConnectionDuration", kStatusConnectedTime, num_expected_authenticated_channels_); - test_clock_->Advance(kStatusAuthenticatedTime); + test_clock_.Advance(kStatusAuthenticatedTime); channel->ChangeStatus(cryptauth::SecureChannel::Status::AUTHENTICATING); channel->ChangeStatus(cryptauth::SecureChannel::Status::AUTHENTICATED); histogram_tester_.ExpectTimeBucketCount( @@ -542,7 +547,7 @@ std::unique_ptr<FakeAdHocBleAdvertiser> fake_ad_hoc_ble_advertiser_; std::unique_ptr<BleAdvertisementDeviceQueue> device_queue_; MockTimerFactory* mock_timer_factory_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; std::unique_ptr<FakeConnectionFactory> fake_connection_factory_; std::unique_ptr<FakeSecureChannelFactory> fake_secure_channel_factory_; std::unique_ptr<TestObserver> test_observer_; @@ -771,10 +776,18 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + VerifyDeviceNotRegistered(test_devices_[0]); + + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); - VerifyDeviceNotRegistered(test_devices_[0]); } // Test for fix to crbug.com/706640. This test will crash without the fix. @@ -827,10 +840,18 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + VerifyDeviceNotRegistered(test_devices_[0]); + + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); - VerifyDeviceNotRegistered(test_devices_[0]); } TEST_F(BleConnectionManagerTest, TestGetStatusForDevice) { @@ -893,14 +914,24 @@ manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status)); EXPECT_EQ(cryptauth::SecureChannel::Status::AUTHENTICATED, status); - // Now, unregister the device and check that GetStatusForDevice() once again - // returns false. + // Now, unregister the device. manager_->UnregisterRemoteDevice( test_devices_[0].GetDeviceId(), ConnectionReason::TETHER_AVAILABILITY_REQUEST); VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + EXPECT_TRUE( + manager_->GetStatusForDevice(test_devices_[0].GetDeviceId(), &status)); + EXPECT_EQ(cryptauth::SecureChannel::Status::DISCONNECTING, status); + + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); @@ -1082,6 +1113,14 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); @@ -1145,10 +1184,18 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + VerifyDeviceNotRegistered(test_devices_[0]); + + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); - VerifyDeviceNotRegistered(test_devices_[0]); manager_->UnregisterRemoteDevice( test_devices_[1].GetDeviceId(), @@ -1156,10 +1203,18 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[1].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + VerifyDeviceNotRegistered(test_devices_[1]); + + fake_secure_channel_factory_->created_channels()[1]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[1].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); - VerifyDeviceNotRegistered(test_devices_[1]); } TEST_F(BleConnectionManagerTest, FourDevices_ComprehensiveTest) { @@ -1235,6 +1290,13 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); @@ -1293,9 +1355,8 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[3].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, - cryptauth::SecureChannel::Status::DISCONNECTED, - BleConnectionManager::StateChangeDetail:: - STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}, {test_devices_[1].GetDeviceId(), cryptauth::SecureChannel::Status::CONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, @@ -1306,6 +1367,15 @@ cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); + + fake_secure_channel_factory_->created_channels()[1]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[3].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, + cryptauth::SecureChannel::Status::DISCONNECTED, + BleConnectionManager::StateChangeDetail:: + STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); } // Regression test for crbug.com/733360. This bug caused a crash when there were @@ -1343,10 +1413,18 @@ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ {test_devices_[0].GetDeviceId(), cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTING, + BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE}}); + VerifyDeviceNotRegistered(test_devices_[0]); + + fake_secure_channel_factory_->created_channels()[0]->ChangeStatus( + cryptauth::SecureChannel::Status::DISCONNECTED); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0].GetDeviceId(), + cryptauth::SecureChannel::Status::DISCONNECTING, cryptauth::SecureChannel::Status::DISCONNECTED, BleConnectionManager::StateChangeDetail:: STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED}}); - VerifyDeviceNotRegistered(test_devices_[0]); // Now, register the device again. This should cause a "disconnected => // connecting" status change. This time, the multiple observers will respond
diff --git a/chromeos/components/tether/ble_synchronizer.cc b/chromeos/components/tether/ble_synchronizer.cc index 57145dba..6b9995e 100644 --- a/chromeos/components/tether/ble_synchronizer.cc +++ b/chromeos/components/tether/ble_synchronizer.cc
@@ -25,7 +25,7 @@ scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) : bluetooth_adapter_(bluetooth_adapter), timer_(std::make_unique<base::OneShotTimer>()), - clock_(std::make_unique<base::DefaultClock>()), + clock_(base::DefaultClock::GetInstance()), task_runner_(base::ThreadTaskRunnerHandle::Get()), weak_ptr_factory_(this) {} @@ -126,10 +126,10 @@ void BleSynchronizer::SetTestDoubles( std::unique_ptr<base::Timer> test_timer, - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, scoped_refptr<base::TaskRunner> test_task_runner) { timer_ = std::move(test_timer); - clock_ = std::move(test_clock); + clock_ = test_clock; task_runner_ = test_task_runner; }
diff --git a/chromeos/components/tether/ble_synchronizer.h b/chromeos/components/tether/ble_synchronizer.h index 995f67d..210bad68 100644 --- a/chromeos/components/tether/ble_synchronizer.h +++ b/chromeos/components/tether/ble_synchronizer.h
@@ -55,7 +55,7 @@ }; void SetTestDoubles(std::unique_ptr<base::Timer> test_timer, - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, scoped_refptr<base::TaskRunner> test_task_runner); void OnAdvertisementRegistered( @@ -87,7 +87,7 @@ std::unique_ptr<Command> current_command_; std::unique_ptr<base::Timer> timer_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; scoped_refptr<base::TaskRunner> task_runner_; base::Time last_command_end_timestamp_; base::WeakPtrFactory<BleSynchronizer> weak_ptr_factory_;
diff --git a/chromeos/components/tether/ble_synchronizer_unittest.cc b/chromeos/components/tether/ble_synchronizer_unittest.cc index 7f9e0a0f..9ab4c618 100644 --- a/chromeos/components/tether/ble_synchronizer_unittest.cc +++ b/chromeos/components/tether/ble_synchronizer_unittest.cc
@@ -227,13 +227,11 @@ mock_timer_ = new base::MockTimer(true /* retain_user_task */, false /* is_repeating */); - test_clock_ = new base::SimpleTestClock(); - test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); + test_clock_.Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); test_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>(); synchronizer_ = std::make_unique<BleSynchronizer>(mock_adapter_); - synchronizer_->SetTestDoubles(base::WrapUnique(mock_timer_), - base::WrapUnique(test_clock_), + synchronizer_->SetTestDoubles(base::WrapUnique(mock_timer_), &test_clock_, test_task_runner_); } @@ -450,7 +448,7 @@ scoped_refptr<NiceMock<MockBluetoothAdapterWithAdvertisements>> mock_adapter_; base::MockTimer* mock_timer_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_; std::vector<std::unique_ptr<RegisterAdvertisementArgs>> register_args_list_; @@ -568,7 +566,7 @@ EXPECT_EQ(1, num_register_success_); // Advance to one millisecond before the limit. - test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs - 1)); + test_clock_.Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs - 1)); UnregisterAdvertisement(); // Should still be empty since it should have been throttled, and the timer @@ -578,7 +576,7 @@ // Advance the clock and fire the timer. This should result in the next // command being executed. - test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); + test_clock_.Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); mock_timer_->Fire(); InvokeUnregisterCallback(true /* success */, 0u /* reg_arg_index */, @@ -594,7 +592,7 @@ // Advance the clock and fire the timer. This should result in the next // command being executed. - test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); + test_clock_.Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); mock_timer_->Fire(); EXPECT_EQ(2u, register_args_list_.size()); @@ -604,7 +602,7 @@ // Advance the clock and fire the timer. This should result in the next // command being executed. - test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); + test_clock_.Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); mock_timer_->Fire(); EXPECT_EQ(3u, register_args_list_.size()); @@ -615,7 +613,7 @@ // Advance the clock before doing anything else. The next request should not // be throttled. EXPECT_FALSE(mock_timer_->IsRunning()); - test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); + test_clock_.Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); UnregisterAdvertisement(); InvokeUnregisterCallback(false /* success */, 1u /* reg_arg_index */,
diff --git a/chromeos/components/tether/connect_tethering_operation.cc b/chromeos/components/tether/connect_tethering_operation.cc index 03af65d..5f3f686a 100644 --- a/chromeos/components/tether/connect_tethering_operation.cc +++ b/chromeos/components/tether/connect_tethering_operation.cc
@@ -75,7 +75,7 @@ connection_manager), remote_device_(device_to_connect), tether_host_response_recorder_(tether_host_response_recorder), - clock_(std::make_unique<base::DefaultClock>()), + clock_(base::DefaultClock::GetInstance()), setup_required_(setup_required), error_code_to_return_( ConnectTetheringResponse_ResponseCode:: @@ -209,9 +209,8 @@ kSetupNotRequiredResponseTimeoutSeconds; } -void ConnectTetheringOperation::SetClockForTest( - std::unique_ptr<base::Clock> clock_for_test) { - clock_ = std::move(clock_for_test); +void ConnectTetheringOperation::SetClockForTest(base::Clock* clock_for_test) { + clock_ = clock_for_test; } } // namespace tether
diff --git a/chromeos/components/tether/connect_tethering_operation.h b/chromeos/components/tether/connect_tethering_operation.h index 9c1efbb..e59014c 100644 --- a/chromeos/components/tether/connect_tethering_operation.h +++ b/chromeos/components/tether/connect_tethering_operation.h
@@ -95,7 +95,7 @@ FRIEND_TEST_ALL_PREFIXES(ConnectTetheringOperationTest, TestOperation_SetupRequired); - void SetClockForTest(std::unique_ptr<base::Clock> clock_for_test); + void SetClockForTest(base::Clock* clock_for_test); // The amount of time this operation will wait for a response. The timeout // values are different depending on whether setup is needed on the host. @@ -104,7 +104,7 @@ cryptauth::RemoteDevice remote_device_; TetherHostResponseRecorder* tether_host_response_recorder_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; int connect_message_sequence_number_ = -1; bool setup_required_;
diff --git a/chromeos/components/tether/connect_tethering_operation_unittest.cc b/chromeos/components/tether/connect_tethering_operation_unittest.cc index da99f65..b5342fb8 100644 --- a/chromeos/components/tether/connect_tethering_operation_unittest.cc +++ b/chromeos/components/tether/connect_tethering_operation_unittest.cc
@@ -124,9 +124,8 @@ mock_tether_host_response_recorder_.get(), false /* setup_required */)); operation_->AddObserver(test_observer_.get()); - test_clock_ = new base::SimpleTestClock(); - test_clock_->SetNow(base::Time::UnixEpoch()); - operation_->SetClockForTest(base::WrapUnique(test_clock_)); + test_clock_.SetNow(base::Time::UnixEpoch()); + operation_->SetClockForTest(&test_clock_); operation_->Initialize(); } @@ -155,7 +154,7 @@ void SimulateResponseReceivedAndVerifyObserverCallbackInvoked( ConnectTetheringResponse_ResponseCode response_code, bool use_proto_without_ssid_and_password) { - test_clock_->Advance(kConnectTetheringResponseTime); + test_clock_.Advance(kConnectTetheringResponseTime); fake_ble_connection_manager_->ReceiveMessage( test_device_.GetDeviceId(), @@ -210,7 +209,7 @@ std::unique_ptr<StrictMock<MockTetherHostResponseRecorder>> mock_tether_host_response_recorder_; std::unique_ptr<TestObserver> test_observer_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; std::unique_ptr<ConnectTetheringOperation> operation_; base::HistogramTester histogram_tester_;
diff --git a/chromeos/components/tether/disconnect_tethering_operation.cc b/chromeos/components/tether/disconnect_tethering_operation.cc index eea2074..777ecd0 100644 --- a/chromeos/components/tether/disconnect_tethering_operation.cc +++ b/chromeos/components/tether/disconnect_tethering_operation.cc
@@ -54,7 +54,7 @@ connection_manager), remote_device_(device_to_connect), has_sent_message_(false), - clock_(std::make_unique<base::DefaultClock>()) {} + clock_(base::DefaultClock::GetInstance()) {} DisconnectTetheringOperation::~DisconnectTetheringOperation() = default; @@ -107,8 +107,8 @@ } void DisconnectTetheringOperation::SetClockForTest( - std::unique_ptr<base::Clock> clock_for_test) { - clock_ = std::move(clock_for_test); + base::Clock* clock_for_test) { + clock_ = clock_for_test; } } // namespace tether
diff --git a/chromeos/components/tether/disconnect_tethering_operation.h b/chromeos/components/tether/disconnect_tethering_operation.h index fe85cfc..a2b2ecd 100644 --- a/chromeos/components/tether/disconnect_tethering_operation.h +++ b/chromeos/components/tether/disconnect_tethering_operation.h
@@ -65,14 +65,14 @@ private: friend class DisconnectTetheringOperationTest; - void SetClockForTest(std::unique_ptr<base::Clock> clock_for_test); + void SetClockForTest(base::Clock* clock_for_test); base::ObserverList<Observer> observer_list_; cryptauth::RemoteDevice remote_device_; int disconnect_message_sequence_number_ = -1; bool has_sent_message_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; base::Time disconnect_start_time_; DISALLOW_COPY_AND_ASSIGN(DisconnectTetheringOperation);
diff --git a/chromeos/components/tether/disconnect_tethering_operation_unittest.cc b/chromeos/components/tether/disconnect_tethering_operation_unittest.cc index c98240c..35c8e5d0 100644 --- a/chromeos/components/tether/disconnect_tethering_operation_unittest.cc +++ b/chromeos/components/tether/disconnect_tethering_operation_unittest.cc
@@ -71,9 +71,8 @@ test_observer_ = base::WrapUnique(new TestObserver()); operation_->AddObserver(test_observer_.get()); - test_clock_ = new base::SimpleTestClock(); - test_clock_->SetNow(base::Time::UnixEpoch()); - operation_->SetClockForTest(base::WrapUnique(test_clock_)); + test_clock_.SetNow(base::Time::UnixEpoch()); + operation_->SetClockForTest(&test_clock_); operation_->Initialize(); } @@ -89,7 +88,7 @@ EXPECT_EQ(test_device_.GetDeviceId(), sent_messages[0].device_id); EXPECT_EQ(disconnect_tethering_request_string_, sent_messages[0].message); - test_clock_->Advance(kDisconnectTetheringRequestTime); + test_clock_.Advance(kDisconnectTetheringRequestTime); // Now, simulate the message being sent. int last_sequence_number = @@ -112,7 +111,7 @@ std::unique_ptr<FakeBleConnectionManager> fake_ble_connection_manager_; std::unique_ptr<TestObserver> test_observer_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; std::unique_ptr<DisconnectTetheringOperation> operation_;
diff --git a/chromeos/components/tether/host_scan_scheduler_impl.cc b/chromeos/components/tether/host_scan_scheduler_impl.cc index ee15198..a335571 100644 --- a/chromeos/components/tether/host_scan_scheduler_impl.cc +++ b/chromeos/components/tether/host_scan_scheduler_impl.cc
@@ -50,7 +50,7 @@ host_scanner_(host_scanner), session_manager_(session_manager), timer_(std::make_unique<base::OneShotTimer>()), - clock_(std::make_unique<base::DefaultClock>()), + clock_(base::DefaultClock::GetInstance()), task_runner_(base::ThreadTaskRunnerHandle::Get()), is_screen_locked_(session_manager_->IsScreenLocked()), weak_ptr_factory_(this) { @@ -137,10 +137,10 @@ void HostScanSchedulerImpl::SetTestDoubles( std::unique_ptr<base::Timer> test_timer, - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, scoped_refptr<base::TaskRunner> test_task_runner) { timer_ = std::move(test_timer); - clock_ = std::move(test_clock); + clock_ = test_clock; task_runner_ = test_task_runner; }
diff --git a/chromeos/components/tether/host_scan_scheduler_impl.h b/chromeos/components/tether/host_scan_scheduler_impl.h index 2ca9677..c9bcb675 100644 --- a/chromeos/components/tether/host_scan_scheduler_impl.h +++ b/chromeos/components/tether/host_scan_scheduler_impl.h
@@ -68,7 +68,7 @@ void LogHostScanBatchMetric(); void SetTestDoubles(std::unique_ptr<base::Timer> test_timer, - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, scoped_refptr<base::TaskRunner> test_task_runner); NetworkStateHandler* network_state_handler_; @@ -76,7 +76,7 @@ session_manager::SessionManager* session_manager_; std::unique_ptr<base::Timer> timer_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; scoped_refptr<base::TaskRunner> task_runner_; base::Time last_scan_batch_start_timestamp_;
diff --git a/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc b/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc index f75d02bc..3c32dee 100644 --- a/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc +++ b/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc
@@ -75,14 +75,12 @@ mock_timer_ = new base::MockTimer(true /* retain_user_task */, false /* is_repeating */); - test_clock_ = new base::SimpleTestClock(); // Advance the clock by an arbitrary value to ensure that when Now() is // called, the Unix epoch will not be returned. - test_clock_->Advance(base::TimeDelta::FromSeconds(10)); + test_clock_.Advance(base::TimeDelta::FromSeconds(10)); test_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>(); host_scan_scheduler_->SetTestDoubles(base::WrapUnique(mock_timer_), - base::WrapUnique(test_clock_), - test_task_runner_); + &test_clock_, test_task_runner_); } void TearDown() override { @@ -162,7 +160,7 @@ std::unique_ptr<session_manager::SessionManager> session_manager_; base::MockTimer* mock_timer_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_; std::unique_ptr<base::HistogramTester> histogram_tester_; @@ -176,7 +174,7 @@ EXPECT_TRUE( network_state_handler()->GetScanningByType(NetworkTypePattern::Tether())); - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); fake_host_scanner_->StopScan(); EXPECT_EQ(1u, fake_host_scanner_->num_scans_started()); EXPECT_FALSE( @@ -210,7 +208,7 @@ EXPECT_TRUE( network_state_handler()->GetScanningByType(NetworkTypePattern::Tether())); - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); fake_host_scanner_->StopScan(); EXPECT_EQ(1u, fake_host_scanner_->num_scans_started()); EXPECT_FALSE( @@ -230,7 +228,7 @@ EXPECT_TRUE( network_state_handler()->GetScanningByType(NetworkTypePattern::Tether())); - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); // Delete |host_scan_scheduler_|, which should cause the metric to be logged. host_scan_scheduler_.reset(); @@ -243,39 +241,39 @@ // The first scan takes 5 seconds. After stopping, the timer should be // running. host_scan_scheduler_->ScheduleScan(); - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); fake_host_scanner_->StopScan(); EXPECT_TRUE(mock_timer_->IsRunning()); // Advance the clock by 1 second and start another scan. The timer should have // been stopped. - test_clock_->Advance(base::TimeDelta::FromSeconds(1)); + test_clock_.Advance(base::TimeDelta::FromSeconds(1)); EXPECT_LT(base::TimeDelta::FromSeconds(1), mock_timer_->GetCurrentDelay()); host_scan_scheduler_->ScheduleScan(); EXPECT_FALSE(mock_timer_->IsRunning()); // Stop the scan; the duration should not have been recorded, and the timer // should be running again. - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); fake_host_scanner_->StopScan(); EXPECT_TRUE(mock_timer_->IsRunning()); // Advance the clock by 59 seconds and start another scan. The timer should // have been stopped. - test_clock_->Advance(base::TimeDelta::FromSeconds(59)); + test_clock_.Advance(base::TimeDelta::FromSeconds(59)); EXPECT_LT(base::TimeDelta::FromSeconds(59), mock_timer_->GetCurrentDelay()); host_scan_scheduler_->ScheduleScan(); EXPECT_FALSE(mock_timer_->IsRunning()); // Stop the scan; the duration should not have been recorded, and the timer // should be running again. - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); fake_host_scanner_->StopScan(); EXPECT_TRUE(mock_timer_->IsRunning()); // Advance the clock by 60 seconds, which should be equal to the timer's // delay. Since this is a MockTimer, we need to manually fire the timer. - test_clock_->Advance(base::TimeDelta::FromSeconds(60)); + test_clock_.Advance(base::TimeDelta::FromSeconds(60)); EXPECT_EQ(base::TimeDelta::FromSeconds(60), mock_timer_->GetCurrentDelay()); mock_timer_->Fire(); @@ -286,10 +284,10 @@ // Now, start a new 5-second scan, then wait for the timer to fire. A new // batch duration should have been logged to metrics. host_scan_scheduler_->ScheduleScan(); - test_clock_->Advance(base::TimeDelta::FromSeconds(5)); + test_clock_.Advance(base::TimeDelta::FromSeconds(5)); fake_host_scanner_->StopScan(); EXPECT_TRUE(mock_timer_->IsRunning()); - test_clock_->Advance(base::TimeDelta::FromSeconds(60)); + test_clock_.Advance(base::TimeDelta::FromSeconds(60)); EXPECT_EQ(base::TimeDelta::FromSeconds(60), mock_timer_->GetCurrentDelay()); mock_timer_->Fire(); VerifyScanDuration(5u /* expected_num_sections */);
diff --git a/chromeos/components/tether/host_scanner_operation.cc b/chromeos/components/tether/host_scanner_operation.cc index f7e1b0e..7494435 100644 --- a/chromeos/components/tether/host_scanner_operation.cc +++ b/chromeos/components/tether/host_scanner_operation.cc
@@ -140,7 +140,7 @@ connection_manager), tether_host_response_recorder_(tether_host_response_recorder), connection_preserver_(connection_preserver), - clock_(std::make_unique<base::DefaultClock>()) {} + clock_(base::DefaultClock::GetInstance()) {} HostScannerOperation::~HostScannerOperation() = default; @@ -244,9 +244,8 @@ return MessageType::TETHER_AVAILABILITY_REQUEST; } -void HostScannerOperation::SetClockForTest( - std::unique_ptr<base::Clock> clock_for_test) { - clock_ = std::move(clock_for_test); +void HostScannerOperation::SetClockForTest(base::Clock* clock_for_test) { + clock_ = clock_for_test; } void HostScannerOperation::RecordTetherAvailabilityResponseDuration(
diff --git a/chromeos/components/tether/host_scanner_operation.h b/chromeos/components/tether/host_scanner_operation.h index 3e6dbd9d..9fbe100 100644 --- a/chromeos/components/tether/host_scanner_operation.h +++ b/chromeos/components/tether/host_scanner_operation.h
@@ -110,12 +110,12 @@ private: friend class HostScannerOperationTest; - void SetClockForTest(std::unique_ptr<base::Clock> clock_for_test); + void SetClockForTest(base::Clock* clock_for_test); void RecordTetherAvailabilityResponseDuration(const std::string device_id); TetherHostResponseRecorder* tether_host_response_recorder_; ConnectionPreserver* connection_preserver_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; base::ObserverList<Observer> observer_list_; std::vector<cryptauth::RemoteDevice> gms_core_notifications_disabled_devices_;
diff --git a/chromeos/components/tether/host_scanner_operation_unittest.cc b/chromeos/components/tether/host_scanner_operation_unittest.cc index 432015ff..b0e71e6 100644 --- a/chromeos/components/tether/host_scanner_operation_unittest.cc +++ b/chromeos/components/tether/host_scanner_operation_unittest.cc
@@ -153,9 +153,8 @@ test_host_scan_device_prioritizer_->VerifyHasBeenPrioritized( remote_devices, operation_->remote_devices()); - test_clock_ = new base::SimpleTestClock(); - test_clock_->SetNow(base::Time::UnixEpoch()); - operation_->SetClockForTest(base::WrapUnique(test_clock_)); + test_clock_.SetNow(base::Time::UnixEpoch()); + operation_->SetClockForTest(&test_clock_); EXPECT_FALSE(test_observer_->has_received_update()); operation_->Initialize(); @@ -192,7 +191,7 @@ size_t num_scanned_device_results_so_far = test_observer_->scanned_devices_so_far().size(); - test_clock_->Advance(kTetherAvailabilityResponseTime); + test_clock_.Advance(kTetherAvailabilityResponseTime); fake_ble_connection_manager_->ReceiveMessage( remote_device.GetDeviceId(), CreateTetherAvailabilityResponseString( @@ -264,7 +263,7 @@ mock_tether_host_response_recorder_; std::unique_ptr<FakeConnectionPreserver> fake_connection_preserver_; std::unique_ptr<TestObserver> test_observer_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; std::unique_ptr<HostScannerOperation> operation_; base::HistogramTester histogram_tester_;
diff --git a/chromeos/components/tether/keep_alive_operation.cc b/chromeos/components/tether/keep_alive_operation.cc index afd907d..28b7e04 100644 --- a/chromeos/components/tether/keep_alive_operation.cc +++ b/chromeos/components/tether/keep_alive_operation.cc
@@ -48,7 +48,7 @@ std::vector<cryptauth::RemoteDevice>{device_to_connect}, connection_manager), remote_device_(device_to_connect), - clock_(std::make_unique<base::DefaultClock>()) {} + clock_(base::DefaultClock::GetInstance()) {} KeepAliveOperation::~KeepAliveOperation() = default; @@ -110,9 +110,8 @@ return MessageType::KEEP_ALIVE_TICKLE; } -void KeepAliveOperation::SetClockForTest( - std::unique_ptr<base::Clock> clock_for_test) { - clock_ = std::move(clock_for_test); +void KeepAliveOperation::SetClockForTest(base::Clock* clock_for_test) { + clock_ = clock_for_test; } } // namespace tether
diff --git a/chromeos/components/tether/keep_alive_operation.h b/chromeos/components/tether/keep_alive_operation.h index 424fb9c..6941feeee 100644 --- a/chromeos/components/tether/keep_alive_operation.h +++ b/chromeos/components/tether/keep_alive_operation.h
@@ -67,10 +67,10 @@ private: friend class KeepAliveOperationTest; - void SetClockForTest(std::unique_ptr<base::Clock> clock_for_test); + void SetClockForTest(base::Clock* clock_for_test); cryptauth::RemoteDevice remote_device_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; base::ObserverList<Observer> observer_list_; base::Time keep_alive_tickle_request_start_time_;
diff --git a/chromeos/components/tether/keep_alive_operation_unittest.cc b/chromeos/components/tether/keep_alive_operation_unittest.cc index f61a7a9..566eaaf0 100644 --- a/chromeos/components/tether/keep_alive_operation_unittest.cc +++ b/chromeos/components/tether/keep_alive_operation_unittest.cc
@@ -84,9 +84,8 @@ test_observer_ = base::WrapUnique(new TestObserver()); operation_->AddObserver(test_observer_.get()); - test_clock_ = new base::SimpleTestClock(); - test_clock_->SetNow(base::Time::UnixEpoch()); - operation_->SetClockForTest(base::WrapUnique(test_clock_)); + test_clock_.SetNow(base::Time::UnixEpoch()); + operation_->SetClockForTest(&test_clock_); operation_->Initialize(); } @@ -106,7 +105,7 @@ const cryptauth::RemoteDevice test_device_; std::unique_ptr<FakeBleConnectionManager> fake_ble_connection_manager_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; std::unique_ptr<TestObserver> test_observer_; std::unique_ptr<KeepAliveOperation> operation_; @@ -123,7 +122,7 @@ SimulateDeviceAuthenticationAndVerifyMessageSent(); EXPECT_FALSE(test_observer_->has_run_callback()); - test_clock_->Advance(kKeepAliveTickleResponseTime); + test_clock_.Advance(kKeepAliveTickleResponseTime); fake_ble_connection_manager_->ReceiveMessage( test_device_.GetDeviceId(), CreateKeepAliveTickleResponseString());
diff --git a/chromeos/components/tether/synchronous_shutdown_object_container_impl.cc b/chromeos/components/tether/synchronous_shutdown_object_container_impl.cc index 2f89061..409979a 100644 --- a/chromeos/components/tether/synchronous_shutdown_object_container_impl.cc +++ b/chromeos/components/tether/synchronous_shutdown_object_container_impl.cc
@@ -136,10 +136,10 @@ asychronous_container->ble_connection_manager(), master_host_scan_cache_.get(), device_id_tether_network_guid_map_.get())), - clock_(std::make_unique<base::DefaultClock>()), hotspot_usage_duration_tracker_( - std::make_unique<HotspotUsageDurationTracker>(active_host_.get(), - clock_.get())), + std::make_unique<HotspotUsageDurationTracker>( + active_host_.get(), + base::DefaultClock::GetInstance())), connection_preserver_(std::make_unique<ConnectionPreserverImpl>( asychronous_container->ble_connection_manager(), network_state_handler_, @@ -157,7 +157,7 @@ device_id_tether_network_guid_map_.get(), master_host_scan_cache_.get(), connection_preserver_.get(), - clock_.get())), + base::DefaultClock::GetInstance())), host_scan_scheduler_( std::make_unique<HostScanSchedulerImpl>(network_state_handler_, host_scanner_.get(), @@ -177,7 +177,7 @@ host_connection_metrics_logger_.get(), asychronous_container->disconnect_tethering_request_sender(), asychronous_container->wifi_hotspot_disconnector(), - clock_.get())), + base::DefaultClock::GetInstance())), tether_disconnector_(std::make_unique<TetherDisconnectorImpl>( active_host_.get(), asychronous_container->wifi_hotspot_disconnector(),
diff --git a/chromeos/components/tether/synchronous_shutdown_object_container_impl.h b/chromeos/components/tether/synchronous_shutdown_object_container_impl.h index 068a5d8..e255d12c 100644 --- a/chromeos/components/tether/synchronous_shutdown_object_container_impl.h +++ b/chromeos/components/tether/synchronous_shutdown_object_container_impl.h
@@ -11,10 +11,6 @@ class PrefService; -namespace base { -class Clock; -} // namespace base - namespace session_manager { class SessionManager; } // namespace session_manager @@ -127,7 +123,6 @@ std::unique_ptr<MasterHostScanCache> master_host_scan_cache_; std::unique_ptr<NotificationRemover> notification_remover_; std::unique_ptr<KeepAliveScheduler> keep_alive_scheduler_; - std::unique_ptr<base::Clock> clock_; std::unique_ptr<HotspotUsageDurationTracker> hotspot_usage_duration_tracker_; std::unique_ptr<ConnectionPreserver> connection_preserver_; std::unique_ptr<HostScanner> host_scanner_;
diff --git a/chromeos/components/tether/wifi_hotspot_connector.cc b/chromeos/components/tether/wifi_hotspot_connector.cc index bc70db5d..27de48c 100644 --- a/chromeos/components/tether/wifi_hotspot_connector.cc +++ b/chromeos/components/tether/wifi_hotspot_connector.cc
@@ -31,7 +31,7 @@ : network_state_handler_(network_state_handler), network_connect_(network_connect), timer_(std::make_unique<base::OneShotTimer>()), - clock_(std::make_unique<base::DefaultClock>()), + clock_(base::DefaultClock::GetInstance()), task_runner_(base::ThreadTaskRunnerHandle::Get()), weak_ptr_factory_(this) { network_state_handler_->AddObserver(this, FROM_HERE); @@ -294,10 +294,10 @@ void WifiHotspotConnector::SetTestDoubles( std::unique_ptr<base::Timer> test_timer, - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, scoped_refptr<base::TaskRunner> test_task_runner) { timer_ = std::move(test_timer); - clock_ = std::move(test_clock); + clock_ = test_clock; task_runner_ = test_task_runner; }
diff --git a/chromeos/components/tether/wifi_hotspot_connector.h b/chromeos/components/tether/wifi_hotspot_connector.h index 7958377df..a7e3f9ec 100644 --- a/chromeos/components/tether/wifi_hotspot_connector.h +++ b/chromeos/components/tether/wifi_hotspot_connector.h
@@ -72,13 +72,13 @@ void OnConnectionTimeout(); void SetTestDoubles(std::unique_ptr<base::Timer> test_timer, - std::unique_ptr<base::Clock> test_clock, + base::Clock* test_clock, scoped_refptr<base::TaskRunner> test_task_runner); NetworkStateHandler* network_state_handler_; NetworkConnect* network_connect_; std::unique_ptr<base::Timer> timer_; - std::unique_ptr<base::Clock> clock_; + base::Clock* clock_; std::string ssid_; std::string password_;
diff --git a/chromeos/components/tether/wifi_hotspot_connector_unittest.cc b/chromeos/components/tether/wifi_hotspot_connector_unittest.cc index 93bf5380..3d08ce7 100644 --- a/chromeos/components/tether/wifi_hotspot_connector_unittest.cc +++ b/chromeos/components/tether/wifi_hotspot_connector_unittest.cc
@@ -176,12 +176,10 @@ mock_timer_ = new base::MockTimer(true /* retain_user_task */, false /* is_repeating */); - test_clock_ = new base::SimpleTestClock(); - test_clock_->SetNow(base::Time::UnixEpoch()); + test_clock_.SetNow(base::Time::UnixEpoch()); test_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>(); wifi_hotspot_connector_->SetTestDoubles(base::WrapUnique(mock_timer_), - base::WrapUnique(test_clock_), - test_task_runner_); + &test_clock_, test_task_runner_); } void SetUpShillState() { @@ -311,7 +309,7 @@ std::vector<std::string> connection_callback_responses_; base::MockTimer* mock_timer_; - base::SimpleTestClock* test_clock_; + base::SimpleTestClock test_clock_; scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_; std::unique_ptr<TestNetworkConnect> test_network_connect_; @@ -448,7 +446,7 @@ EXPECT_EQ(wifi_guid, test_network_connect_->network_id_to_connect()); EXPECT_EQ(0u, connection_callback_responses_.size()); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Connection to network successful. NotifyConnected(test_network_connect_->last_service_path_created()); @@ -476,7 +474,7 @@ EXPECT_EQ(wifi_guid, test_network_connect_->network_id_to_connect()); EXPECT_EQ(0u, connection_callback_responses_.size()); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Connection to network successful. NotifyConnected(test_network_connect_->last_service_path_created()); @@ -504,7 +502,7 @@ // Pass some arbitrary time -- this should not affect the // recorded duration because the start time should be reset // for a new network attempt. - test_clock_->Advance(base::TimeDelta::FromSeconds(13)); + test_clock_.Advance(base::TimeDelta::FromSeconds(13)); // Before network becomes connectable, start the new connection. EXPECT_EQ(0u, connection_callback_responses_.size()); @@ -533,7 +531,7 @@ EXPECT_TRUE(test_network_connect_->network_id_to_connect().empty()); EXPECT_EQ(1u, connection_callback_responses_.size()); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Second network becomes connectable. NotifyConnectable(service_path2); @@ -563,7 +561,7 @@ // Pass some arbitrary time -- this should not affect the // recorded duration because the start time should be reset // for a new network attempt. - test_clock_->Advance(base::TimeDelta::FromSeconds(13)); + test_clock_.Advance(base::TimeDelta::FromSeconds(13)); std::string wifi_guid1 = VerifyLastConfiguration("ssid1", "password1"); EXPECT_FALSE(wifi_guid1.empty()); @@ -603,7 +601,7 @@ EXPECT_NE(service_path1, service_path2); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Second network becomes connectable. NotifyConnectable(service_path2); @@ -652,7 +650,7 @@ VerifyLastConfiguration(std::string(kSsid), std::string(kPassword)); EXPECT_FALSE(wifi_guid.empty()); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Network becomes connectable. NotifyConnectable(test_network_connect_->last_service_path_created()); @@ -715,7 +713,7 @@ EXPECT_EQ(wifi_guid, test_network_connect_->network_id_to_connect()); EXPECT_EQ(0u, connection_callback_responses_.size()); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Connection to network successful. NotifyConnected(test_network_connect_->last_service_path_created()); @@ -778,7 +776,7 @@ // Pass some arbitrary time -- this should not affect the // recorded duration because the start time should be reset // for a new network attempt. - test_clock_->Advance(base::TimeDelta::FromSeconds(13)); + test_clock_.Advance(base::TimeDelta::FromSeconds(13)); EXPECT_FALSE(test_network_connect_->last_configuration()); @@ -814,7 +812,7 @@ EXPECT_EQ(wifi_guid2, test_network_connect_->network_id_to_connect()); EXPECT_EQ(1u, connection_callback_responses_.size()); - test_clock_->Advance(kConnectionToHotspotTime); + test_clock_.Advance(kConnectionToHotspotTime); // Connection to network successful. NotifyConnected(service_path2);
diff --git a/chromeos/dbus/fake_update_engine_client.cc b/chromeos/dbus/fake_update_engine_client.cc index 859cfd9..ccd22b5b 100644 --- a/chromeos/dbus/fake_update_engine_client.cc +++ b/chromeos/dbus/fake_update_engine_client.cc
@@ -85,11 +85,10 @@ FROM_HERE, base::Bind(callback, std::string())); } -void FakeUpdateEngineClient::GetEolStatus( - const GetEolStatusCallback& callback) { +void FakeUpdateEngineClient::GetEolStatus(GetEolStatusCallback callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(callback, update_engine::EndOfLifeStatus::kSupported)); + FROM_HERE, base::BindOnce(std::move(callback), + update_engine::EndOfLifeStatus::kSupported)); } void FakeUpdateEngineClient::SetUpdateOverCellularPermission(
diff --git a/chromeos/dbus/fake_update_engine_client.h b/chromeos/dbus/fake_update_engine_client.h index 2b49014..eaf1460 100644 --- a/chromeos/dbus/fake_update_engine_client.h +++ b/chromeos/dbus/fake_update_engine_client.h
@@ -35,7 +35,7 @@ bool is_powerwash_allowed) override; void GetChannel(bool get_current_channel, const GetChannelCallback& callback) override; - void GetEolStatus(const GetEolStatusCallback& callback) override; + void GetEolStatus(GetEolStatusCallback callback) override; void SetUpdateOverCellularPermission(bool allowed, const base::Closure& callback) override; void SetUpdateOverCellularOneTimePermission(
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc index efbb907..10f1189a 100644 --- a/chromeos/dbus/update_engine_client.cc +++ b/chromeos/dbus/update_engine_client.cc
@@ -206,7 +206,7 @@ weak_ptr_factory_.GetWeakPtr(), callback)); } - void GetEolStatus(const GetEolStatusCallback& callback) override { + void GetEolStatus(GetEolStatusCallback callback) override { dbus::MethodCall method_call(update_engine::kUpdateEngineInterface, update_engine::kGetEolStatus); @@ -214,7 +214,7 @@ update_engine_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&UpdateEngineClientImpl::OnGetEolStatus, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void SetUpdateOverCellularPermission(bool allowed, @@ -414,18 +414,17 @@ } // Called when a response for GetEolStatus() is received. - void OnGetEolStatus(const GetEolStatusCallback& callback, - dbus::Response* response) { + void OnGetEolStatus(GetEolStatusCallback callback, dbus::Response* response) { if (!response) { LOG(ERROR) << "Failed to request getting eol status"; - callback.Run(update_engine::EndOfLifeStatus::kSupported); + std::move(callback).Run(update_engine::EndOfLifeStatus::kSupported); return; } dbus::MessageReader reader(response); int status; if (!reader.PopInt32(&status)) { LOG(ERROR) << "Incorrect response: " << response->ToString(); - callback.Run(update_engine::EndOfLifeStatus::kSupported); + std::move(callback).Run(update_engine::EndOfLifeStatus::kSupported); return; } @@ -433,12 +432,13 @@ if (status > update_engine::EndOfLifeStatus::kEol || status < update_engine::EndOfLifeStatus::kSupported) { LOG(ERROR) << "Incorrect status value: " << status; - callback.Run(update_engine::EndOfLifeStatus::kSupported); + std::move(callback).Run(update_engine::EndOfLifeStatus::kSupported); return; } VLOG(1) << "Eol status received: " << status; - callback.Run(static_cast<update_engine::EndOfLifeStatus>(status)); + std::move(callback).Run( + static_cast<update_engine::EndOfLifeStatus>(status)); } // Called when a response for SetUpdateOverCellularPermission() is received. @@ -599,8 +599,8 @@ callback.Run(target_channel_); } - void GetEolStatus(const GetEolStatusCallback& callback) override { - callback.Run(update_engine::EndOfLifeStatus::kSupported); + void GetEolStatus(GetEolStatusCallback callback) override { + std::move(callback).Run(update_engine::EndOfLifeStatus::kSupported); } void SetUpdateOverCellularPermission(bool allowed,
diff --git a/chromeos/dbus/update_engine_client.h b/chromeos/dbus/update_engine_client.h index df23e5ab..f942536 100644 --- a/chromeos/dbus/update_engine_client.h +++ b/chromeos/dbus/update_engine_client.h
@@ -145,10 +145,10 @@ // Called once GetEolStatus() is complete. Takes one parameter; // - EndOfLife Status: the end of life status of the device. using GetEolStatusCallback = - base::Callback<void(update_engine::EndOfLifeStatus status)>; + base::OnceCallback<void(update_engine::EndOfLifeStatus status)>; // Get EndOfLife status of the device and calls |callback| when completed. - virtual void GetEolStatus(const GetEolStatusCallback& callback) = 0; + virtual void GetEolStatus(GetEolStatusCallback callback) = 0; // Either allow or disallow receiving updates over cellular connections. // Synchronous (blocking) method.
diff --git a/components/arc/volume_mounter/arc_volume_mounter_bridge.cc b/components/arc/volume_mounter/arc_volume_mounter_bridge.cc index 7cf9eb0..f6a180f8 100644 --- a/components/arc/volume_mounter/arc_volume_mounter_bridge.cc +++ b/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
@@ -18,15 +18,6 @@ namespace { -// Sends MountEvents of all existing MountPoints in cros-disks. -void SendAllMountEvents(ArcVolumeMounterBridge* bridge) { - for (const auto& keyValue : DiskMountManager::GetInstance()->mount_points()) { - bridge->OnMountEvent(DiskMountManager::MountEvent::MOUNTING, - chromeos::MountError::MOUNT_ERROR_NONE, - keyValue.second); - } -} - // Singleton factory for ArcVolumeMounterBridge. class ArcVolumeMounterBridgeFactory : public internal::ArcBrowserContextKeyedServiceFactoryBase< @@ -56,7 +47,7 @@ ArcVolumeMounterBridge::ArcVolumeMounterBridge(content::BrowserContext* context, ArcBridgeService* bridge_service) - : arc_bridge_service_(bridge_service) { + : arc_bridge_service_(bridge_service), weak_ptr_factory_(this) { arc_bridge_service_->volume_mounter()->AddObserver(this); DCHECK(DiskMountManager::GetInstance()); DiskMountManager::GetInstance()->AddObserver(this); @@ -67,11 +58,21 @@ arc_bridge_service_->volume_mounter()->RemoveObserver(this); } +// Sends MountEvents of all existing MountPoints in cros-disks. +void ArcVolumeMounterBridge::SendAllMountEvents() { + for (const auto& keyValue : DiskMountManager::GetInstance()->mount_points()) { + OnMountEvent(DiskMountManager::MountEvent::MOUNTING, + chromeos::MountError::MOUNT_ERROR_NONE, keyValue.second); + } +} + void ArcVolumeMounterBridge::OnConnectionReady() { - base::PostTaskWithTraits(FROM_HERE, - {base::TaskPriority::USER_BLOCKING, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce(&SendAllMountEvents, this)); + // Deferring the SendAllMountEvents as a task to current thread to not + // block the mojo request since SendAllMountEvents might takes non trivial + // amount of time. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&ArcVolumeMounterBridge::SendAllMountEvents, + weak_ptr_factory_.GetWeakPtr())); } void ArcVolumeMounterBridge::OnAutoMountableDiskEvent(
diff --git a/components/arc/volume_mounter/arc_volume_mounter_bridge.h b/components/arc/volume_mounter/arc_volume_mounter_bridge.h index 5c47f2cf..ebca095 100644 --- a/components/arc/volume_mounter/arc_volume_mounter_bridge.h +++ b/components/arc/volume_mounter/arc_volume_mounter_bridge.h
@@ -8,6 +8,7 @@ #include <string> #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chromeos/disks/disk_mount_manager.h" #include "components/arc/common/volume_mounter.mojom.h" #include "components/arc/connection_observer.h" @@ -62,8 +63,12 @@ const std::string& device_path) override; private: + void SendAllMountEvents(); + ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager. + base::WeakPtrFactory<ArcVolumeMounterBridge> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(ArcVolumeMounterBridge); };
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc index 0ddd6ce..e3935b3c4 100644 --- a/components/autofill/core/browser/credit_card_save_manager.cc +++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -37,7 +37,7 @@ #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_util.h" #include "components/prefs/pref_service.h" -#include "google_apis/gaia/identity_provider.h" +#include "services/identity/public/cpp/identity_manager.h" #include "url/gurl.h" namespace autofill { @@ -209,7 +209,7 @@ return observer_for_testing_ || ::autofill::IsCreditCardUploadEnabled( client_->GetPrefs(), client_->GetSyncService(), - client_->GetIdentityProvider()->GetActiveUsername()); + client_->GetIdentityManager()->GetPrimaryAccountInfo().email); } void CreditCardSaveManager::OnDidUploadCard(
diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc index 4b046908..56dea701 100644 --- a/components/autofill/core/common/form_field_data.cc +++ b/components/autofill/core/common/form_field_data.cc
@@ -121,10 +121,9 @@ } bool HaveSameLabel(const FormFieldData& field1, const FormFieldData& field2) { - if (field1.label == field2.label && - field1.label_source == field2.label_source) { + if (field1.label == field2.label) return true; - } + // Assume the labels same if they come from same source but not LABEL tag // when kAutofillSkipComparingInferredLabels is enabled. if (base::FeatureList::IsEnabled( @@ -254,10 +253,6 @@ return true; if (text_direction > field.text_direction) return false; - if (label_source < field.label_source) - return true; - if (label_source > field.label_source) - return false; // See SameFieldAs above for why we don't check option_values/contents. return false; }
diff --git a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc index 4c3f2c4..d338b05a 100644 --- a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc +++ b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc
@@ -167,6 +167,19 @@ BluetoothLowEnergyWeaveClientConnection:: ~BluetoothLowEnergyWeaveClientConnection() { + if (sub_status() != SubStatus::DISCONNECTED) { + // Deleting this object without calling Disconnect() may result in the + // connection staying active longer than intended, which can lead to errors. + // See https://crbug.com/763604. + PA_LOG(WARNING) << "Warning: Deleting " + << "BluetoothLowEnergyWeaveClientConnection object with an " + << "active connection to " << GetDeviceInfoLogString() + << ". This may result in disconnection errors; trying to " + << "send uWeave \"connection close\" packet before " + << "deleting."; + ClearQueueAndSendConnectionClose(); + } + DestroyConnection( BleWeaveConnectionResult::BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); } @@ -233,6 +246,11 @@ void BluetoothLowEnergyWeaveClientConnection::Disconnect() { if (IsConnected()) { + // If a disconnection is already in progress, there is nothing to do. + if (has_triggered_disconnection_) + return; + + has_triggered_disconnection_ = true; PA_LOG(INFO) << "Disconnection requested; sending \"connection close\" " << "uWeave packet to " << GetDeviceInfoLogString() << "."; @@ -721,6 +739,8 @@ WriteRequestType::CONNECTION_CLOSE) { // Once a "connection close" uWeave packet has been sent, the connection // is ready to be disconnected. + PA_LOG(INFO) << "uWeave \"connection close\" packet sent to " + << GetDeviceInfoLogString() << ". Destroying connection."; DestroyConnection( BleWeaveConnectionResult::BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); return; @@ -839,9 +859,11 @@ if (pending_write_request_) { PA_LOG(WARNING) << "Waiting for current write to complete, then will send " - << "a \"connection close\" uWeave packet."; + << "a \"connection close\" uWeave packet to " + << GetDeviceInfoLogString() << "."; } else { - PA_LOG(INFO) << "Sending a \"connection close\" uWeave packet."; + PA_LOG(INFO) << "Sending a \"connection close\" uWeave packet to " + << GetDeviceInfoLogString() << "."; } ProcessNextWriteRequest();
diff --git a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h index 75d76e3..fe5e5c4 100644 --- a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h +++ b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h
@@ -173,6 +173,8 @@ FRIEND_TEST_ALL_PREFIXES(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, ConnectSuccessDisconnect); FRIEND_TEST_ALL_PREFIXES(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, + DisconnectCalledTwice); + FRIEND_TEST_ALL_PREFIXES(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, ConnectSuccessDisconnect_DoNotSetLowLatency); FRIEND_TEST_ALL_PREFIXES( CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, @@ -358,6 +360,8 @@ bool should_set_low_connection_latency_; + bool has_triggered_disconnection_ = false; + // Tracks if the result of this connection has been recorded (using // BleWeaveConnectionResult). The result of a connection should only be // recorded once.
diff --git a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc index b6700096..9aea84df 100644 --- a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc +++ b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc
@@ -564,9 +564,6 @@ connection->Disconnect(); if (connection->IsConnected()) { - connection->DestroyConnection( - BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: - BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); EXPECT_EQ(last_value_written_on_tx_characteristic_, kConnectionCloseSuccess); RunWriteCharacteristicSuccessCallback(); @@ -576,6 +573,21 @@ EXPECT_EQ(connection->status(), Connection::DISCONNECTED); } + void DeleteConnectionWithoutCallingDisconnect( + std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection>* + connection) { + bool was_connected = (*connection)->IsConnected(); + if (was_connected) { + EXPECT_CALL(*tx_characteristic_, WriteRemoteCharacteristic(_, _, _)) + .WillOnce( + DoAll(SaveArg<0>(&last_value_written_on_tx_characteristic_), + SaveArg<1>(&write_remote_characteristic_success_callback_), + SaveArg<2>(&write_remote_characteristic_error_callback_))); + } + + connection->reset(); + } + void InitializeConnection( TestBluetoothLowEnergyWeaveClientConnection* connection, uint32_t selected_packet_size) { @@ -707,7 +719,7 @@ CreateConnection(true /* should_set_low_connection_latency */)); Disconnect(connection.get()); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -722,7 +734,7 @@ NotifySessionStarted(connection.get()); ConnectionResponseReceived(connection.get(), kDefaultMaxPacketSize); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -742,6 +754,34 @@ } TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, + DisconnectCalledTwice) { + std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection> connection( + CreateConnection(true /* should_set_low_connection_latency */)); + InitializeConnection(connection.get(), kDefaultMaxPacketSize); + EXPECT_EQ(connection->sub_status(), SubStatus::CONNECTED_AND_IDLE); + + EXPECT_CALL(*tx_characteristic_, WriteRemoteCharacteristic(_, _, _)) + .WillOnce( + DoAll(SaveArg<0>(&last_value_written_on_tx_characteristic_), + SaveArg<1>(&write_remote_characteristic_success_callback_), + SaveArg<2>(&write_remote_characteristic_error_callback_))); + + // Call Disconnect() twice; this should only result in one "close connection" + // message (verified via WillOnce() above). + connection->Disconnect(); + connection->Disconnect(); + + EXPECT_EQ(last_value_written_on_tx_characteristic_, kConnectionCloseSuccess); + RunWriteCharacteristicSuccessCallback(); + + EXPECT_EQ(connection->sub_status(), SubStatus::DISCONNECTED); + EXPECT_EQ(connection->status(), Connection::DISCONNECTED); + VerifyBleWeaveConnectionResult( + BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: + BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); +} + +TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, ConnectSuccessDisconnect_DoNotSetLowLatency) { std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection> connection( CreateConnection(false /* should_set_low_connection_latency */)); @@ -774,7 +814,7 @@ CharacteristicsFound(connection.get()); Disconnect(connection.get()); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -922,7 +962,7 @@ EXPECT_EQ(received_bytes, kSmallMessage); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -947,7 +987,7 @@ } EXPECT_EQ(received_bytes, kLargeMessage); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -979,7 +1019,7 @@ EXPECT_EQ(kSmallMessage, connection_observer_->GetLastDeserializedMessage()); EXPECT_TRUE(connection_observer_->last_send_success()); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -1030,7 +1070,7 @@ EXPECT_EQ(kLargeMessage, connection_observer_->GetLastDeserializedMessage()); EXPECT_TRUE(connection_observer_->last_send_success()); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -1214,7 +1254,8 @@ InitializeConnection(connection, kDefaultMaxPacketSize); EXPECT_CALL(*tx_characteristic_, WriteRemoteCharacteristic(_, _, _)) - .WillOnce( + .Times(2) + .WillRepeatedly( DoAll(SaveArg<0>(&last_value_written_on_tx_characteristic_), SaveArg<1>(&write_remote_characteristic_success_callback_), SaveArg<2>(&write_remote_characteristic_error_callback_))); @@ -1230,6 +1271,9 @@ EXPECT_EQ(kSmallMessage, connection_observer_->GetLastDeserializedMessage()); EXPECT_TRUE(connection_observer_->last_send_success()); + // Connection close packet should have been sent when the object was deleted. + EXPECT_EQ(last_value_written_on_tx_characteristic_, kConnectionCloseSuccess); + // We cannot check if connection's status and sub_status are DISCONNECTED // because it has been deleted. @@ -1330,7 +1374,7 @@ VerifyGattConnectionResultSuccess(); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY); @@ -1375,7 +1419,7 @@ VerifyGattConnectionResultSuccess(); - connection.reset(); + DeleteConnectionWithoutCallingDisconnect(&connection); VerifyBleWeaveConnectionResult( BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult:: BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
diff --git a/components/cryptauth/fake_secure_channel.cc b/components/cryptauth/fake_secure_channel.cc index fd21916..9fbe29c8 100644 --- a/components/cryptauth/fake_secure_channel.cc +++ b/components/cryptauth/fake_secure_channel.cc
@@ -63,7 +63,13 @@ } void FakeSecureChannel::Disconnect() { - ChangeStatus(Status::DISCONNECTED); + if (status() == Status::DISCONNECTING || status() == Status::DISCONNECTED) + return; + + if (status() == Status::CONNECTING) + ChangeStatus(Status::DISCONNECTED); + else + ChangeStatus(Status::DISCONNECTING); } void FakeSecureChannel::AddObserver(Observer* observer) {
diff --git a/components/cryptauth/secure_channel.cc b/components/cryptauth/secure_channel.cc index 2639bdf6..bcf3d296 100644 --- a/components/cryptauth/secure_channel.cc +++ b/components/cryptauth/secure_channel.cc
@@ -53,6 +53,8 @@ return "[authenticating]"; case Status::AUTHENTICATED: return "[authenticated]"; + case Status::DISCONNECTING: + return "[disconnecting]"; default: return "[unknown status]"; } @@ -100,6 +102,8 @@ void SecureChannel::Disconnect() { if (connection_->IsConnected()) { + TransitionToStatus(Status::DISCONNECTING); + // If |connection_| is active, calling Disconnect() will eventually cause // its status to transition to DISCONNECTED, which will in turn cause this // class to transition to DISCONNECTED.
diff --git a/components/cryptauth/secure_channel.h b/components/cryptauth/secure_channel.h index 913c659..a9b941af 100644 --- a/components/cryptauth/secure_channel.h +++ b/components/cryptauth/secure_channel.h
@@ -37,12 +37,15 @@ // process of authenticating via a 3-message authentication handshake. // AUTHENTICATED: The connection has been authenticated, and arbitrary // messages can be sent/received to/from the device. + // DISCONNECTING: The connection has started disconnecting but has not yet + // finished. enum class Status { DISCONNECTED, CONNECTING, CONNECTED, AUTHENTICATING, AUTHENTICATED, + DISCONNECTING }; static std::string StatusToString(const Status& status);
diff --git a/components/cryptauth/secure_channel_unittest.cc b/components/cryptauth/secure_channel_unittest.cc index 34a190c..bfcdbcc 100644 --- a/components/cryptauth/secure_channel_unittest.cc +++ b/components/cryptauth/secure_channel_unittest.cc
@@ -452,12 +452,11 @@ }); FailAuthentication(Authenticator::Result::DISCONNECTED); - VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> { - { - SecureChannel::Status::AUTHENTICATING, - SecureChannel::Status::DISCONNECTED - } - }); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {SecureChannel::Status::AUTHENTICATING, + SecureChannel::Status::DISCONNECTING}, + {SecureChannel::Status::DISCONNECTING, + SecureChannel::Status::DISCONNECTED}}); } TEST_F(CryptAuthSecureChannelTest, AuthenticationFails_Failure) { @@ -482,12 +481,11 @@ }); FailAuthentication(Authenticator::Result::FAILURE); - VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> { - { - SecureChannel::Status::AUTHENTICATING, - SecureChannel::Status::DISCONNECTED - } - }); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {SecureChannel::Status::AUTHENTICATING, + SecureChannel::Status::DISCONNECTING}, + {SecureChannel::Status::DISCONNECTING, + SecureChannel::Status::DISCONNECTED}}); } // Regression test for crbug.com/765810. This test ensures that a crash does not @@ -556,12 +554,11 @@ TEST_F(CryptAuthSecureChannelTest, SendMessage_Failure) { ConnectAndAuthenticate(); StartAndFinishSendingMessage("feature", "payload", /* success */ false); - VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> { - { - SecureChannel::Status::AUTHENTICATED, - SecureChannel::Status::DISCONNECTED - } - }); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {SecureChannel::Status::AUTHENTICATED, + SecureChannel::Status::DISCONNECTING}, + {SecureChannel::Status::DISCONNECTING, + SecureChannel::Status::DISCONNECTED}}); } TEST_F(CryptAuthSecureChannelTest, SendMessage_Success) { @@ -601,12 +598,11 @@ FinishSendingMessage(sequence_number1, false); // The connection should have become disconnected. - VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> { - { - SecureChannel::Status::AUTHENTICATED, - SecureChannel::Status::DISCONNECTED - } - }); + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {SecureChannel::Status::AUTHENTICATED, + SecureChannel::Status::DISCONNECTING}, + {SecureChannel::Status::DISCONNECTING, + SecureChannel::Status::DISCONNECTED}}); // The first message failed, so no other ones should be tried afterward. VerifyNoMessageBeingSent();
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index 6a1be07..222126c 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -250,11 +250,8 @@ aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); - // 1) Initial state, no shadow. - wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); - ASSERT_TRUE(shadow); - EXPECT_FALSE(shadow->layer()->visible()); - + // 1) Initial state, no shadow (SurfaceFrameType is NONE); + EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); std::unique_ptr<Display> display(new Display); // 2) Just creating a sub surface won't create a shadow. @@ -266,11 +263,14 @@ display->CreateSubSurface(child.get(), surface.get())); surface->Commit(); - EXPECT_FALSE(shadow->layer()->visible()); + EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); // 3) Create a shadow. + surface->SetFrame(SurfaceFrameType::NORMAL); shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); surface->Commit(); + wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); + ASSERT_TRUE(shadow); EXPECT_TRUE(shadow->layer()->visible()); gfx::Rect before = shadow->layer()->bounds(); @@ -321,6 +321,7 @@ const gfx::Rect original_bounds(gfx::Point(10, 10), content_size); shell_surface->SetGeometry(original_bounds); surface->Attach(buffer.get()); + surface->SetFrame(SurfaceFrameType::NORMAL); surface->Commit(); // Placing a shadow at screen origin will make the shadow's origin (-10, -10). @@ -379,6 +380,7 @@ const gfx::Rect original_bounds(gfx::Point(10, 10), content_size); shell_surface->SetGeometry(original_bounds); surface->Attach(buffer.get()); + surface->SetFrame(SurfaceFrameType::NORMAL); surface->Commit(); aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); @@ -408,6 +410,7 @@ exo_test_helper()->CreateClientControlledShellSurface(surface.get()); shell_surface->SetMaximized(); surface->Attach(buffer.get()); + surface->SetFrame(SurfaceFrameType::NORMAL); surface->Commit(); views::Widget* widget = shell_surface->GetWidget(); @@ -416,7 +419,7 @@ // There is no shadow when started in maximized state. EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); - // Sending a shadow bounds in maximized state won't create a shaodw. + // Sending a shadow bounds in maximized state won't create a shadow. shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); surface->Commit(); EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window));
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index 76c49ee6..72e89ad04 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -904,7 +904,8 @@ UpdateSurfaceBounds(); // The shadow size may be updated to match the widget. Change it back - // to the shadow content size. + // to the shadow content size. Note that this relies on wm::ShadowController + // being notified of the change before |this|. UpdateShadow(); Configure();
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index caea5b6..73a7603d 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -603,9 +603,8 @@ TemplateURLService* template_url_service) { if (!allowed_to_be_default_match) { const GURL& stripped_canonical_input_url = - AutocompleteMatch::GURLToStrippedGURL( - input.canonicalized_url(), input, template_url_service, - base::string16()); + GURLToStrippedGURL(input.canonicalized_url(), input, + template_url_service, base::string16()); ComputeStrippedDestinationURL(input, template_url_service); allowed_to_be_default_match = stripped_canonical_input_url == stripped_destination_url;
diff --git a/components/omnibox/browser/base_search_provider_unittest.cc b/components/omnibox/browser/base_search_provider_unittest.cc index 0387a0a..ec6d575 100644 --- a/components/omnibox/browser/base_search_provider_unittest.cc +++ b/components/omnibox/browser/base_search_provider_unittest.cc
@@ -79,15 +79,15 @@ nullptr, std::unique_ptr<SearchTermsData>(new SearchTermsData), nullptr, std::unique_ptr<TemplateURLServiceClient>(), nullptr, nullptr, base::Closure())); - client_.reset(new NiceMock<MockAutocompleteProviderClient>()); + client_.reset(new MockAutocompleteProviderClient()); client_->set_template_url_service(std::move(template_url_service)); provider_ = new NiceMock<TestBaseSearchProvider>( AutocompleteProvider::TYPE_SEARCH, client_.get()); } base::test::ScopedTaskEnvironment scoped_task_environment_; - scoped_refptr<NiceMock<TestBaseSearchProvider> > provider_; - std::unique_ptr<NiceMock<MockAutocompleteProviderClient>> client_; + scoped_refptr<NiceMock<TestBaseSearchProvider>> provider_; + std::unique_ptr<MockAutocompleteProviderClient> client_; }; TEST_F(BaseSearchProviderTest, PreserveAnswersWhenDeduplicating) {
diff --git a/components/omnibox/browser/bookmark_provider_unittest.cc b/components/omnibox/browser/bookmark_provider_unittest.cc index 4b83b25d..d37d993 100644 --- a/components/omnibox/browser/bookmark_provider_unittest.cc +++ b/components/omnibox/browser/bookmark_provider_unittest.cc
@@ -186,8 +186,7 @@ } void BookmarkProviderTest::SetUp() { - provider_client_.reset( - new testing::NiceMock<MockAutocompleteProviderClient>()); + provider_client_.reset(new MockAutocompleteProviderClient()); EXPECT_CALL(*provider_client_, GetBookmarkModel()) .WillRepeatedly(testing::Return(model_.get())); EXPECT_CALL(*provider_client_, GetSchemeClassifier())
diff --git a/components/omnibox/browser/clipboard_url_provider_unittest.cc b/components/omnibox/browser/clipboard_url_provider_unittest.cc index 5222d955..becd43b 100644 --- a/components/omnibox/browser/clipboard_url_provider_unittest.cc +++ b/components/omnibox/browser/clipboard_url_provider_unittest.cc
@@ -25,8 +25,9 @@ class ClipboardURLProviderTest : public testing::Test { public: ClipboardURLProviderTest() - : client_(new testing::NiceMock<MockAutocompleteProviderClient>()), - provider_(new ClipboardURLProvider(client_.get(), nullptr, + : client_(new MockAutocompleteProviderClient()), + provider_(new ClipboardURLProvider(client_.get(), + nullptr, &clipboard_content_)) { SetClipboardUrl(GURL(kClipboardURL)); } @@ -51,7 +52,7 @@ protected: TestSchemeClassifier classifier_; FakeClipboardRecentContent clipboard_content_; - std::unique_ptr<testing::NiceMock<MockAutocompleteProviderClient>> client_; + std::unique_ptr<MockAutocompleteProviderClient> client_; scoped_refptr<ClipboardURLProvider> provider_; };
diff --git a/components/omnibox/browser/contextual_suggestions_service.cc b/components/omnibox/browser/contextual_suggestions_service.cc index eae95a9..470cd6f 100644 --- a/components/omnibox/browser/contextual_suggestions_service.cc +++ b/components/omnibox/browser/contextual_suggestions_service.cc
@@ -152,12 +152,11 @@ GURL ContextualSuggestionsService::ExperimentalContextualSuggestionsUrl( const std::string& current_url, const TemplateURLService* template_url_service) const { - if (current_url.empty()) { + if (current_url.empty() || template_url_service == nullptr) { return GURL(); } - if (!base::FeatureList::IsEnabled(omnibox::kZeroSuggestRedirectToChrome) || - template_url_service == nullptr) { + if (!base::FeatureList::IsEnabled(omnibox::kZeroSuggestRedirectToChrome)) { return GURL(); }
diff --git a/components/omnibox/browser/keyword_provider_unittest.cc b/components/omnibox/browser/keyword_provider_unittest.cc index b3c04d6..9b2ad91 100644 --- a/components/omnibox/browser/keyword_provider_unittest.cc +++ b/components/omnibox/browser/keyword_provider_unittest.cc
@@ -131,10 +131,9 @@ }; void KeywordProviderTest::SetUpClientAndKeywordProvider() { - std::unique_ptr<TemplateURLService> template_url_service( - new TemplateURLService(kTestData, arraysize(kTestData))); client_.reset(new MockAutocompleteProviderClient()); - client_->set_template_url_service(std::move(template_url_service)); + client_->set_template_url_service( + std::make_unique<TemplateURLService>(kTestData, arraysize(kTestData))); kw_provider_ = new KeywordProvider(client_.get(), nullptr); }
diff --git a/components/omnibox/browser/mock_autocomplete_provider_client.h b/components/omnibox/browser/mock_autocomplete_provider_client.h index 9aeaa2df..372f498 100644 --- a/components/omnibox/browser/mock_autocomplete_provider_client.h +++ b/components/omnibox/browser/mock_autocomplete_provider_client.h
@@ -20,7 +20,8 @@ struct AutocompleteMatch; -class MockAutocompleteProviderClient : public AutocompleteProviderClient { +class MockAutocompleteProviderClient + : public testing::NiceMock<AutocompleteProviderClient> { public: MockAutocompleteProviderClient(); ~MockAutocompleteProviderClient();
diff --git a/components/omnibox/browser/omnibox_popup_model.cc b/components/omnibox/browser/omnibox_popup_model.cc index 8a43604..6eff8366 100644 --- a/components/omnibox/browser/omnibox_popup_model.cc +++ b/components/omnibox/browser/omnibox_popup_model.cc
@@ -15,8 +15,6 @@ #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/browser/omnibox_popup_model_observer.h" #include "components/omnibox/browser/omnibox_popup_view.h" -#include "components/search_engines/template_url.h" -#include "components/search_engines/template_url_service.h" #include "third_party/icu/source/common/unicode/ubidi.h" #include "ui/gfx/geometry/rect.h"
diff --git a/components/omnibox/browser/physical_web_provider_unittest.cc b/components/omnibox/browser/physical_web_provider_unittest.cc index 7409c4b6..b360a65 100644 --- a/components/omnibox/browser/physical_web_provider_unittest.cc +++ b/components/omnibox/browser/physical_web_provider_unittest.cc
@@ -37,8 +37,7 @@ // An autocomplete provider client that embeds the fake Physical Web data // source. -class FakeAutocompleteProviderClient - : public testing::NiceMock<MockAutocompleteProviderClient> { +class FakeAutocompleteProviderClient : public MockAutocompleteProviderClient { public: FakeAutocompleteProviderClient() : physical_web_data_source_(
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc index f387753..6ca8dbcc 100644 --- a/components/omnibox/browser/search_provider.cc +++ b/components/omnibox/browser/search_provider.cc
@@ -99,17 +99,17 @@ : template_url_service_(template_url_service) {} const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { - return default_provider_.empty() - ? nullptr - : template_url_service_->GetTemplateURLForKeyword( - default_provider_); + if (default_provider_.empty()) + return nullptr; + DCHECK(template_url_service_); + return template_url_service_->GetTemplateURLForKeyword(default_provider_); } const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() const { - return keyword_provider_.empty() - ? nullptr - : template_url_service_->GetTemplateURLForKeyword( - keyword_provider_); + if (keyword_provider_.empty()) + return nullptr; + DCHECK(template_url_service_); + return template_url_service_->GetTemplateURLForKeyword(keyword_provider_); }
diff --git a/components/omnibox/browser/test_omnibox_client.cc b/components/omnibox/browser/test_omnibox_client.cc index c747b37..b988ed2 100644 --- a/components/omnibox/browser/test_omnibox_client.cc +++ b/components/omnibox/browser/test_omnibox_client.cc
@@ -32,7 +32,7 @@ std::unique_ptr<AutocompleteProviderClient> TestOmniboxClient::CreateAutocompleteProviderClient() { std::unique_ptr<MockAutocompleteProviderClient> provider_client( - new testing::NiceMock<MockAutocompleteProviderClient>()); + new MockAutocompleteProviderClient()); EXPECT_CALL(*provider_client.get(), GetBuiltinURLs()) .WillRepeatedly(testing::Return(std::vector<base::string16>())); EXPECT_CALL(*provider_client.get(), GetSchemeClassifier())
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index ceac475..5bebca99 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -413,6 +413,7 @@ matches_.clear(); TemplateURLService* template_url_service = client()->GetTemplateURLService(); + DCHECK(template_url_service); const TemplateURL* default_provider = template_url_service->GetDefaultSearchProvider(); // Fail if we can't set the clickthrough URL for query suggestions. @@ -539,6 +540,7 @@ // Check if the URL can be sent in any suggest request. const TemplateURLService* template_url_service = client()->GetTemplateURLService(); + DCHECK(template_url_service); const TemplateURL* default_provider = template_url_service->GetDefaultSearchProvider(); const bool can_send_current_url = CanSendURL(
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc index 9214be1..f516833 100644 --- a/components/omnibox/browser/zero_suggest_provider_unittest.cc +++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -102,8 +102,7 @@ mv_callback = callback; } -class FakeAutocompleteProviderClient - : public testing::NiceMock<MockAutocompleteProviderClient> { +class FakeAutocompleteProviderClient : public MockAutocompleteProviderClient { public: FakeAutocompleteProviderClient() : template_url_service_(new TemplateURLService(nullptr, 0)),
diff --git a/components/printing/browser/print_manager_utils.cc b/components/printing/browser/print_manager_utils.cc index a661d71..5bd1fd71 100644 --- a/components/printing/browser/print_manager_utils.cc +++ b/components/printing/browser/print_manager_utils.cc
@@ -28,14 +28,17 @@ void CreateCompositeClientIfNeeded(content::WebContents* web_contents, bool for_preview) { // TODO(weili): We only create pdf compositor client and use pdf compositor - // service when site-per-process flag or feature is enabled, or - // top-document-isolation feature is enabled. This doesn't cover all cases - // where OOPIF is used such as isolate-origin, but should be good for feature - // testing purpose. Eventually, we will remove this check and use pdf + // service when site-per-process or isolate-origins flag/feature is enabled, + // or top-document-isolation feature is enabled. This may not cover all cases + // where OOPIF is used such as isolate-extensions, but should be good for + // feature testing purpose. Eventually, we will remove this check and use pdf // compositor service by default for printing. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kSitePerProcess) || + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kIsolateOrigins) || base::FeatureList::IsEnabled(features::kSitePerProcess) || + base::FeatureList::IsEnabled(features::kIsolateOrigins) || base::FeatureList::IsEnabled(features::kTopDocumentIsolation)) { PrintCompositeClient::CreateForWebContents(web_contents); if (for_preview) {
diff --git a/components/resources/default_100_percent/crash/favicon_sad_tab.png b/components/resources/default_100_percent/crash/favicon_sad_tab.png index dcec70d8..cae8e61 100644 --- a/components/resources/default_100_percent/crash/favicon_sad_tab.png +++ b/components/resources/default_100_percent/crash/favicon_sad_tab.png Binary files differ
diff --git a/components/resources/default_100_percent/favicon_history.png b/components/resources/default_100_percent/favicon_history.png index 3af97be3..0de9a3f 100644 --- a/components/resources/default_100_percent/favicon_history.png +++ b/components/resources/default_100_percent/favicon_history.png Binary files differ
diff --git a/components/resources/default_100_percent/flags_ui/favicon_flags.png b/components/resources/default_100_percent/flags_ui/favicon_flags.png index b27a223..0f6d8d0 100644 --- a/components/resources/default_100_percent/flags_ui/favicon_flags.png +++ b/components/resources/default_100_percent/flags_ui/favicon_flags.png Binary files differ
diff --git a/components/resources/default_200_percent/crash/favicon_sad_tab.png b/components/resources/default_200_percent/crash/favicon_sad_tab.png index 9c434b9..bae8abb 100644 --- a/components/resources/default_200_percent/crash/favicon_sad_tab.png +++ b/components/resources/default_200_percent/crash/favicon_sad_tab.png Binary files differ
diff --git a/components/resources/default_200_percent/favicon_history.png b/components/resources/default_200_percent/favicon_history.png index a07ed66e..126e8ddf 100644 --- a/components/resources/default_200_percent/favicon_history.png +++ b/components/resources/default_200_percent/favicon_history.png Binary files differ
diff --git a/components/resources/default_200_percent/flags_ui/favicon_flags.png b/components/resources/default_200_percent/flags_ui/favicon_flags.png index 3b3d3722..d7da8a87 100644 --- a/components/resources/default_200_percent/flags_ui/favicon_flags.png +++ b/components/resources/default_200_percent/flags_ui/favicon_flags.png Binary files differ
diff --git a/components/resources/default_300_percent/crash/favicon_sad_tab.png b/components/resources/default_300_percent/crash/favicon_sad_tab.png index 26221c6..8ca9ee8a 100644 --- a/components/resources/default_300_percent/crash/favicon_sad_tab.png +++ b/components/resources/default_300_percent/crash/favicon_sad_tab.png Binary files differ
diff --git a/components/resources/default_300_percent/favicon_history.png b/components/resources/default_300_percent/favicon_history.png index c4c58862..0c174e1 100644 --- a/components/resources/default_300_percent/favicon_history.png +++ b/components/resources/default_300_percent/favicon_history.png Binary files differ
diff --git a/components/resources/default_300_percent/flags_ui/favicon_flags.png b/components/resources/default_300_percent/flags_ui/favicon_flags.png index 14d8551..801b8604 100644 --- a/components/resources/default_300_percent/flags_ui/favicon_flags.png +++ b/components/resources/default_300_percent/flags_ui/favicon_flags.png Binary files differ
diff --git a/components/resources/sadtab.svg b/components/resources/sadtab.svg index 9ce9ccb..58579d6 100644 --- a/components/resources/sadtab.svg +++ b/components/resources/sadtab.svg
@@ -1,4 +1,4 @@ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48px" viewbox="0 0 48 48" fill="none"> - <path stroke="#5a5a5a" stroke-width="3" stroke-linecap="square" d="M1.5 8.5 v34 h45 v-28 m-3-3 h-10 v-3 m-3-3 h-10 m15 6 h-18 v-3 m-3-3 h-10"/> - <path stroke="#5a5a5a" stroke-width="2" stroke-linecap="square" d="M12 35 h2 m2-2 h12 m2 2 h3 m2 2 h3 M11 21 l0 0 m0 4 h0 m4 0 h0 m0-4 h0 m-2 2 h0 M33 21 l0 0 m0 4 h0 m4 0 h0 m0-4 h0 m-2 2 h0"/> + <path stroke="#757575" stroke-width="3" stroke-linecap="square" d="M1.5 8.5 v34 h45 v-28 m-3-3 h-10 v-3 m-3-3 h-10 m15 6 h-18 v-3 m-3-3 h-10"/> + <path stroke="#757575" stroke-width="2" stroke-linecap="square" d="M12 35 h2 m2-2 h12 m2 2 h3 m2 2 h3 M11 21 l0 0 m0 4 h0 m4 0 h0 m0-4 h0 m-2 2 h0 M33 21 l0 0 m0 4 h0 m4 0 h0 m0-4 h0 m-2 2 h0"/> </svg>
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn index 06519c8..90e00b4 100644 --- a/components/search_engines/BUILD.gn +++ b/components/search_engines/BUILD.gn
@@ -121,6 +121,7 @@ "keyword_table_unittest.cc", "search_engine_data_type_controller_unittest.cc", "search_host_to_urls_map_unittest.cc", + "template_url_data_unittest.cc", "template_url_prepopulate_data_unittest.cc", "template_url_service_util_unittest.cc", "template_url_unittest.cc",
diff --git a/components/search_engines/template_url_data.cc b/components/search_engines/template_url_data.cc index 19a5eee..1bf7f24 100644 --- a/components/search_engines/template_url_data.cc +++ b/components/search_engines/template_url_data.cc
@@ -88,6 +88,8 @@ // Case sensitive keyword matching is confusing. As such, we force all // keywords to be lower case. keyword_ = base::i18n::ToLower(keyword); + + base::TrimWhitespace(keyword_, base::TRIM_ALL, &keyword_); } void TemplateURLData::SetURL(const std::string& url) {
diff --git a/components/search_engines/template_url_data_unittest.cc b/components/search_engines/template_url_data_unittest.cc new file mode 100644 index 0000000..1ee8ec6c --- /dev/null +++ b/components/search_engines/template_url_data_unittest.cc
@@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/search_engines/template_url_data.h" + +#include "base/strings/string_piece.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(TemplateURLDataTest, Trim) { + TemplateURLData data( + base::ASCIIToUTF16(" shortname "), base::ASCIIToUTF16(" keyword "), + "https://cs.chromium.org", base::StringPiece(), base::StringPiece(), + base::StringPiece(), base::StringPiece(), base::StringPiece(), + base::StringPiece(), base::StringPiece(), base::StringPiece(), + base::StringPiece(), base::StringPiece(), base::StringPiece(), + base::ListValue(), 0); + + EXPECT_EQ(base::ASCIIToUTF16("shortname"), data.short_name()); + EXPECT_EQ(base::ASCIIToUTF16("keyword"), data.keyword()); + + data.SetShortName(base::ASCIIToUTF16(" othershortname ")); + data.SetKeyword(base::ASCIIToUTF16(" otherkeyword ")); + + EXPECT_EQ(base::ASCIIToUTF16("othershortname"), data.short_name()); + EXPECT_EQ(base::ASCIIToUTF16("otherkeyword"), data.keyword()); +}
diff --git a/components/translate/core/browser/translate_prefs.cc b/components/translate/core/browser/translate_prefs.cc index de42244..f2143e1 100644 --- a/components/translate/core/browser/translate_prefs.cc +++ b/components/translate/core/browser/translate_prefs.cc
@@ -102,7 +102,7 @@ base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kRegionalLocalesAsDisplayUI{ - "RegionalLocalesAsDisplayUI", base::FEATURE_DISABLED_BY_DEFAULT}; + "RegionalLocalesAsDisplayUI", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kTranslateRecentTarget{"TranslateRecentTarget", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn index 910abf9..bd2a7fbb 100644 --- a/components/variations/BUILD.gn +++ b/components/variations/BUILD.gn
@@ -83,7 +83,6 @@ "//components/crash/core/common:crash_key", "//components/prefs", "//crypto", - "//third_party/mt19937ar", "//third_party/protobuf:protobuf_lite", "//third_party/zlib/google:compression_utils", ]
diff --git a/components/variations/DEPS b/components/variations/DEPS index 720e034..9f3a0436 100644 --- a/components/variations/DEPS +++ b/components/variations/DEPS
@@ -8,7 +8,6 @@ "+components/variations", "+crypto", "-net", - "+third_party/mt19937ar", "+third_party/protobuf", "+third_party/zlib/google", ]
diff --git a/components/variations/entropy_provider.cc b/components/variations/entropy_provider.cc index b6aece8..897b4fa6 100644 --- a/components/variations/entropy_provider.cc +++ b/components/variations/entropy_provider.cc
@@ -19,9 +19,8 @@ namespace internal { -SeededRandGenerator::SeededRandGenerator(uint32_t seed) { - mersenne_twister_.init_genrand(seed); -} +SeededRandGenerator::SeededRandGenerator(uint32_t seed) + : mersenne_twister_(seed) {} SeededRandGenerator::~SeededRandGenerator() { } @@ -39,7 +38,7 @@ uint32_t value; do { - value = mersenne_twister_.genrand_int32(); + value = mersenne_twister_(); } while (value > max_acceptable_value); return value % range;
diff --git a/components/variations/entropy_provider.h b/components/variations/entropy_provider.h index d39b6f8..29001f1 100644 --- a/components/variations/entropy_provider.h +++ b/components/variations/entropy_provider.h
@@ -9,13 +9,13 @@ #include <stdint.h> #include <functional> +#include <random> #include <string> #include <vector> #include "base/compiler_specific.h" #include "base/macros.h" #include "base/metrics/field_trial.h" -#include "third_party/mt19937ar/mt19937ar.h" namespace variations { @@ -31,7 +31,7 @@ // Returns a random number in range [0, range). uint32_t operator()(uint32_t range); - MersenneTwister mersenne_twister_; + std::mt19937 mersenne_twister_; }; // Fills |mapping| to create a bijection of values in the range of
diff --git a/components/viz/common/surfaces/parent_local_surface_id_allocator.cc b/components/viz/common/surfaces/parent_local_surface_id_allocator.cc index f8f1509..3716021 100644 --- a/components/viz/common/surfaces/parent_local_surface_id_allocator.cc +++ b/components/viz/common/surfaces/parent_local_surface_id_allocator.cc
@@ -23,6 +23,11 @@ return last_known_local_surface_id_; } +void ParentLocalSurfaceIdAllocator::Reset( + const LocalSurfaceId& local_surface_id) { + last_known_local_surface_id_ = local_surface_id; +} + const LocalSurfaceId& ParentLocalSurfaceIdAllocator::GenerateId() { ++last_known_local_surface_id_.parent_sequence_number_; return last_known_local_surface_id_;
diff --git a/components/viz/common/surfaces/parent_local_surface_id_allocator.h b/components/viz/common/surfaces/parent_local_surface_id_allocator.h index ed531b53..a1b32a9 100644 --- a/components/viz/common/surfaces/parent_local_surface_id_allocator.h +++ b/components/viz/common/surfaces/parent_local_surface_id_allocator.h
@@ -34,6 +34,9 @@ const LocalSurfaceId& UpdateFromChild( const LocalSurfaceId& child_allocated_local_surface_id); + // Resets this allocator with the provided |local_surface_id| as a seed. + void Reset(const LocalSurfaceId& local_surface_id); + const LocalSurfaceId& GenerateId(); const LocalSurfaceId& last_known_local_surface_id() const {
diff --git a/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc b/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc index 68f7093..37f2acd 100644 --- a/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc +++ b/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc
@@ -131,6 +131,35 @@ generating_parent_allocator.last_known_local_surface_id()); } +// This test verifies that calling reset with a LocalSurfaceId updates the +// last_known_local_surface_id and affects GenerateId. +TEST(ParentLocalSurfaceIdAllocatorTest, ResetUpdatesComponents) { + ParentLocalSurfaceIdAllocator default_constructed_parent_allocator; + + LocalSurfaceId default_local_surface_id = + default_constructed_parent_allocator.last_known_local_surface_id(); + EXPECT_FALSE(default_local_surface_id.is_valid()); + EXPECT_TRUE(ParentSequenceNumberIsNotSet(default_local_surface_id)); + EXPECT_TRUE(ChildSequenceNumberIsSet(default_local_surface_id)); + EXPECT_FALSE(NonceIsEmpty(default_local_surface_id)); + + LocalSurfaceId new_local_surface_id( + 1u, 1u, base::UnguessableToken::Deserialize(0, 1u)); + + default_constructed_parent_allocator.Reset(new_local_surface_id); + EXPECT_EQ(new_local_surface_id, + default_constructed_parent_allocator.last_known_local_surface_id()); + + LocalSurfaceId generated_id = + default_constructed_parent_allocator.GenerateId(); + + EXPECT_EQ(generated_id.nonce(), new_local_surface_id.nonce()); + EXPECT_EQ(generated_id.child_sequence_number(), + new_local_surface_id.child_sequence_number()); + EXPECT_EQ(generated_id.parent_sequence_number(), + new_local_surface_id.child_sequence_number() + 1); +} + namespace { ::testing::AssertionResult ParentSequenceNumberIsNotSet(
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 707dc27..5ee1877d 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -569,8 +569,8 @@ int minimum_draw_occlusion_width = settings_.kMinimumDrawOcclusionSize.width() * device_scale_factor_; - // This the minimum size required to apply layer occlusion, set in - // |LayerTreeSettings::minimum_occlusion_tracking_size|. + // The 160 comes from the LayerTreeSettings::minimum_occlusion_tracking_size + // default value, which is not accessible from here. gfx::Size layer_occlusion_skip_rect_size(160 * device_scale_factor_, 160 * device_scale_factor_); @@ -629,7 +629,9 @@ if (quad->visible_rect.width() <= layer_occlusion_skip_rect_size.width() && quad->visible_rect.height() <= - layer_occlusion_skip_rect_size.height()) { + layer_occlusion_skip_rect_size.height() && + quad->visible_rect.height() >= minimum_draw_occlusion_height && + quad->visible_rect.width() >= minimum_draw_occlusion_width) { total_small_quads += 1; } @@ -700,6 +702,10 @@ } else { total_quad_with_complex_transform += 1; occlusion_in_quad_content_space = gfx::Rect(); + + UMA_HISTOGRAM_COUNTS_1M( + "Compositing.Display.Draw.Quads.With.Complex.Transform.Area", + quad->visible_rect.height() * quad->visible_rect.width()); } } @@ -763,8 +769,8 @@ ? 0 : total_area_saved_in_px * 100 / total_quad_area_shown_wo_occlusion_px); - UMA_HISTOGRAM_COUNTS_10000( - "Compositing.Display.Draw.Occlusion.Drawing.Area.Saved", + UMA_HISTOGRAM_COUNTS_1M( + "Compositing.Display.Draw.Occlusion.Drawing.Area.Saved2", total_area_saved_in_px); }
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index e761a23..d125b45e 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -2096,15 +2096,6 @@ EXPECT_TRUE(HasTemporaryReference(child_id2)); EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1)); - // GetLatestInFlightSurface will not return child_id2's surface because it - // does not yet have an owner. - EXPECT_EQ(GetSurfaceForId(child_id1), - GetLatestInFlightSurface(child_id3, child_id1)); - - // Now that the owner of |child_id2| is known, GetLatestInFlightSurface will - // return it as a possible fallback. - frame_sink_manager().surface_manager()->AssignTemporaryReference( - child_id2, parent_id.frame_sink_id()); EXPECT_EQ(GetSurfaceForId(child_id2), GetLatestInFlightSurface(child_id3, child_id1)); @@ -2121,18 +2112,9 @@ // Verify that there is a temporary reference for child_id3. EXPECT_TRUE(HasTemporaryReference(child_id3)); - // GetLatestInFlightSurface will not return child_id3's surface because it - // does not yet have an owner. - EXPECT_EQ(GetSurfaceForId(child_id2), - GetLatestInFlightSurface(child_id4, child_id1)); - EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1)); - - // Now that the owner of |child_id3| is known, GetLatestInFlightSurface will - // return it as a possible fallback. - frame_sink_manager().surface_manager()->AssignTemporaryReference( - child_id3, parent_id.frame_sink_id()); EXPECT_EQ(GetSurfaceForId(child_id3), GetLatestInFlightSurface(child_id4, child_id1)); + EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1)); // If the primary surface is old, then we shouldn't return an in-flight // surface that is newer than the primary. @@ -2225,30 +2207,71 @@ child_support1().SubmitCompositorFrame(child_id2.local_surface_id(), MakeDefaultCompositorFrame()); - // |child_id2| will not be returned until its temporary reference is - // assigned. - EXPECT_EQ(GetSurfaceForId(child_id1), - GetLatestInFlightSurface(child_id3, child_id1)); - - // Verify that there is a temporary reference for |child_id2|. - EXPECT_TRUE(HasTemporaryReference(child_id2)); - frame_sink_manager().surface_manager()->AssignTemporaryReference( - child_id2, parent_id.frame_sink_id()); - EXPECT_EQ(GetSurfaceForId(child_id2), GetLatestInFlightSurface(child_id3, child_id1)); child_support1().SubmitCompositorFrame(child_id3.local_surface_id(), MakeDefaultCompositorFrame()); - frame_sink_manager().surface_manager()->AssignTemporaryReference( - child_id3, parent_id.frame_sink_id()); - // Even though there is a valid temporary reference with an owner for - // the primary, we never pick the primary. + // GetLatestInFlightSurface will never return the primary surface ID + // even if it's available. EXPECT_EQ(GetSurfaceForId(child_id2), GetLatestInFlightSurface(child_id3, child_id1)); } +// This test verifies that GetLatestInFlightSurface will skip a surface if +// its nonce is different. +TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceSkipDifferentNonce) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + const base::UnguessableToken nonce1( + base::UnguessableToken::Deserialize(0, 1)); + const base::UnguessableToken nonce2( + base::UnguessableToken::Deserialize(1, 1)); + const base::UnguessableToken nonce3( + base::UnguessableToken::Deserialize(2, 1)); + const SurfaceId child_id1 = + SurfaceId(kChildFrameSink1, LocalSurfaceId(1, nonce1)); + const SurfaceId child_id2 = + SurfaceId(kChildFrameSink1, LocalSurfaceId(2, nonce1)); + const SurfaceId child_id3 = + SurfaceId(kChildFrameSink1, LocalSurfaceId(3, nonce2)); + const SurfaceId child_id4 = + SurfaceId(kChildFrameSink1, LocalSurfaceId(4, nonce2)); + const SurfaceId child_id5 = + SurfaceId(kChildFrameSink1, LocalSurfaceId(5, nonce3)); + + // Don't automatically assign temporary references. + DisableAssignTemporaryReferences(); + + child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), + MakeDefaultCompositorFrame()); + + // Create a reference from |parent_id| to |child_id|. + parent_support().SubmitCompositorFrame( + parent_id.local_surface_id(), + MakeCompositorFrame(empty_surface_ids(), {child_id1}, + std::vector<TransferableResource>())); + + child_support1().SubmitCompositorFrame(child_id2.local_surface_id(), + MakeDefaultCompositorFrame()); + + EXPECT_EQ(GetSurfaceForId(child_id2), + GetLatestInFlightSurface(child_id4, child_id1)); + + child_support1().SubmitCompositorFrame(child_id3.local_surface_id(), + MakeDefaultCompositorFrame()); + + // GetLatestInFlightSurface will return child_id3 because the nonce + // matches that of child_id4. + EXPECT_EQ(GetSurfaceForId(child_id3), + GetLatestInFlightSurface(child_id4, child_id1)); + + // GetLatestInFlightSurface will return child_id2 because the nonce + // doesn't match |child_id1| or |child_id5|. + EXPECT_EQ(GetSurfaceForId(child_id2), + GetLatestInFlightSurface(child_id5, child_id1)); +} + // This test verifies that if a child submits a LocalSurfaceId newer that the // parent's dependency, then the parent will drop its dependency and activate // if possible.
diff --git a/components/viz/service/surfaces/surface_manager.cc b/components/viz/service/surfaces/surface_manager.cc index 39ad27d7..48b4b4e 100644 --- a/components/viz/service/surfaces/surface_manager.cc +++ b/components/viz/service/surfaces/surface_manager.cc
@@ -451,9 +451,6 @@ if (it == temporary_reference_ranges_.end()) return fallback_surface; - const base::flat_set<SurfaceId>& fallback_parents = - GetSurfacesThatReferenceChild(fallback_surface_id); - const std::vector<LocalSurfaceId>& temp_surfaces = it->second; for (const LocalSurfaceId& local_surface_id : base::Reversed(temp_surfaces)) { // The in-flight surface must be older than the primary surface ID. @@ -465,14 +462,16 @@ continue; } - SurfaceId surface_id(fallback_surface_id.frame_sink_id(), local_surface_id); - base::Optional<FrameSinkId> owner = temporary_references_[surface_id].owner; - // Determine if the owner of this temporary reference matches one of the - // parents of the fallback surface. Typically a surface has a single parent - // so this operation should be cheap. - if (!IsOwnerAmongFallbackParents(fallback_parents, owner)) + // If the nonce doesn't match the primary or fallback's then the parent does + // not have permission to embed this surface. + if (local_surface_id.nonce() != + fallback_surface_id.local_surface_id().nonce() && + local_surface_id.nonce() != + primary_surface_id.local_surface_id().nonce()) { continue; + } + SurfaceId surface_id(fallback_surface_id.frame_sink_id(), local_surface_id); Surface* surface = GetSurfaceForId(surface_id); if (surface && surface->HasActiveFrame()) return surface; @@ -622,18 +621,6 @@ return surfaces_to_destroy_.count(surface_id) != 0; } -bool SurfaceManager::IsOwnerAmongFallbackParents( - const base::flat_set<SurfaceId>& fallback_parents, - const base::Optional<FrameSinkId>& owner) const { - if (!owner) - return false; - - return std::find_if(fallback_parents.begin(), fallback_parents.end(), - [owner](const SurfaceId& parent) { - return parent.frame_sink_id() == owner; - }) != fallback_parents.end(); -} - void SurfaceManager::SurfaceWillBeDrawn(Surface* surface) { for (auto& observer : observer_list_) observer.OnSurfaceWillBeDrawn(surface);
diff --git a/components/viz/service/surfaces/surface_manager.h b/components/viz/service/surfaces/surface_manager.h index 80749cb..11bf3d30 100644 --- a/components/viz/service/surfaces/surface_manager.h +++ b/components/viz/service/surfaces/surface_manager.h
@@ -299,12 +299,6 @@ // Returns true if |surface_id| is in the garbage collector's queue. bool IsMarkedForDestruction(const SurfaceId& surface_id); - // Determines if the provided |owner| FrameSinkId matches the FrameSinkId of - // a surface in the set of |fallback_parents|. - bool IsOwnerAmongFallbackParents( - const base::flat_set<SurfaceId>& fallback_parents, - const base::Optional<FrameSinkId>& owner) const; - base::Optional<uint32_t> activation_deadline_in_frames_; // SurfaceDependencyTracker needs to be destroyed after Surfaces are destroyed
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 5f9ea0bf0..3e1786a 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -354,17 +354,18 @@ DCHECK(GetWebContents()->GetRenderViewHost()); - // Initialize the device scale factor by calling |NotifyScreenInfoChanged|. - auto* render_widget_host = RenderWidgetHostImpl::From( - GetWebContents()->GetRenderViewHost()->GetWidget()); - render_widget_host->NotifyScreenInfoChanged(); - // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will // be reset again the next time preferences are updated. WebPreferences prefs = GetWebContents()->GetRenderViewHost()->GetWebkitPreferences(); prefs.navigate_on_drag_drop = false; GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs); + + base::Optional<viz::LocalSurfaceId> child_local_surface_id; + if (local_surface_id_.is_valid()) + child_local_surface_id = local_surface_id_; + SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_Attach_ACK>( + browser_plugin_instance_id(), child_local_surface_id)); } BrowserPluginGuest::~BrowserPluginGuest() { @@ -1056,9 +1057,10 @@ const ScreenInfo& screen_info, uint64_t sequence_number, const viz::LocalSurfaceId& local_surface_id) { - if ((frame_rect_.size() != frame_rect.size() || - screen_info_ != screen_info) && - local_surface_id_ == local_surface_id) { + if (local_surface_id_ > local_surface_id || + ((frame_rect_.size() != frame_rect.size() || + screen_info_ != screen_info) && + local_surface_id_ == local_surface_id)) { SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance(); bad_message::ReceivedBadMessage( owner_site_instance->GetProcess(),
diff --git a/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc b/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc index 7ae0b33..1d04bb4 100644 --- a/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc +++ b/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
@@ -42,6 +42,7 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_storage_partition.h" #include "content/public/test/test_utils.h" +#include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_store.h" #include "net/http/http_network_session.h" #include "net/http/http_transaction_factory.h" @@ -267,9 +268,9 @@ new MessageLoopRunner(); quit_closure_ = message_loop_runner->QuitClosure(); get_cookie_success_ = false; - cookie_store_->GetCookiesWithOptionsAsync( + cookie_store_->GetCookieListWithOptionsAsync( kOrigin1, net::CookieOptions(), - base::BindOnce(&RemoveCookieTester::GetCookieCallback, + base::BindOnce(&RemoveCookieTester::GetCookieListCallback, base::Unretained(this))); message_loop_runner->Run(); return get_cookie_success_; @@ -292,11 +293,13 @@ } private: - void GetCookieCallback(const std::string& cookies) { - if (cookies == "A=1") { + void GetCookieListCallback(const net::CookieList& cookie_list) { + std::string cookie_line = + net::CanonicalCookie::BuildCookieLine(cookie_list); + if (cookie_line == std::string("A=1")) { get_cookie_success_ = true; } else { - EXPECT_EQ("", cookies); + EXPECT_EQ("", cookie_line); get_cookie_success_ = false; } quit_closure_.Run();
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc index e84ab8b..d1a4d2f 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -168,11 +168,9 @@ } void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) { - host_->WasResized(); } void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) { - SetSize(rect.size()); } void RenderWidgetHostViewGuest::Focus() {
diff --git a/content/browser/loader/mime_sniffing_resource_handler.cc b/content/browser/loader/mime_sniffing_resource_handler.cc index 23098abc3d..a9322bc 100644 --- a/content/browser/loader/mime_sniffing_resource_handler.cc +++ b/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -513,12 +513,9 @@ } // Attempt to intercept the request as a stream. - base::FilePath plugin_path; - if (has_plugin) - plugin_path = plugin.path; std::string payload; - std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream( - plugin_path, request(), response_.get(), &payload)); + std::unique_ptr<ResourceHandler> handler( + host_->MaybeInterceptAsStream(request(), response_.get(), &payload)); if (handler) { if (!CheckResponseIsNotProvisional()) return false;
diff --git a/content/browser/loader/mime_sniffing_resource_handler_unittest.cc b/content/browser/loader/mime_sniffing_resource_handler_unittest.cc index 4ee8298..60db4bac 100644 --- a/content/browser/loader/mime_sniffing_resource_handler_unittest.cc +++ b/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
@@ -74,7 +74,6 @@ } std::unique_ptr<ResourceHandler> MaybeInterceptAsStream( - const base::FilePath& plugin_path, net::URLRequest* request, network::ResourceResponse* response, std::string* payload) override {
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc index ce518de..051e7ae7 100644 --- a/content/browser/loader/mojo_async_resource_handler_unittest.cc +++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -147,7 +147,6 @@ } bool ShouldInterceptResourceAsStream(net::URLRequest* request, - const base::FilePath& plugin_path, const std::string& mime_type, GURL* origin, std::string* payload) override {
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc index 4aa59d3..01257fc 100644 --- a/content/browser/loader/prefetch_url_loader_service.cc +++ b/content/browser/loader/prefetch_url_loader_service.cc
@@ -17,79 +17,9 @@ #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/url_request/url_request_context_getter.h" #include "services/network/public/cpp/features.h" -#include "services/network/public/mojom/url_loader_factory.mojom.h" namespace content { -namespace { - -// Per-frame URLLoaderFactory. Used only when Network Service is enabled. -class PrefetchURLLoaderFactory : public network::mojom::URLLoaderFactory, - public blink::mojom::PrefetchURLLoaderService { - public: - PrefetchURLLoaderFactory( - content::PrefetchURLLoaderService* service, - scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter, - int frame_tree_node_id) - : service_(std::move(service)), - loader_factory_getter_(std::move(loader_factory_getter)), - frame_tree_node_id_(frame_tree_node_id) {} - ~PrefetchURLLoaderFactory() override = default; - - // blink::mojom::PrefetchURLLoaderService: - void GetFactory(network::mojom::URLLoaderFactoryRequest request) override { - Clone(std::move(request)); - } - - private: - // network::mojom::URLLoaderFactory: - void CreateLoaderAndStart(network::mojom::URLLoaderRequest request, - int32_t routing_id, - int32_t request_id, - uint32_t options, - const network::ResourceRequest& resource_request, - network::mojom::URLLoaderClientPtr client, - const net::MutableNetworkTrafficAnnotationTag& - traffic_annotation) override { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); - if (!network_loader_factory_ || - network_loader_factory_.encountered_error()) { - loader_factory_getter_->GetNetworkFactory()->Clone( - mojo::MakeRequest(&network_loader_factory_)); - } - service_->CreateLoaderAndStart( - std::move(request), routing_id, request_id, options, resource_request, - std::move(client), traffic_annotation, - // NOTE: This should be fine in most cases, where the loader - // factory may become invalid if Network Service process is killed - // and restarted. The load can just fail in the case here, but if - // we want to be extra sure this should create a SharedURLLoaderFactory - // that internally holds a ref to the URLLoaderFactoryGetter so that - // it can re-obtain the factory if necessary. - base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>( - network_loader_factory_.get()), - frame_tree_node_id_); - } - - void Clone(network::mojom::URLLoaderFactoryRequest request) override { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - bindings_.AddBinding(this, std::move(request)); - } - - scoped_refptr<content::PrefetchURLLoaderService> service_; - - network::mojom::URLLoaderFactoryPtr network_loader_factory_; - scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_; - int frame_tree_node_id_; - - mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_; - - DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoaderFactory); -}; - -} // namespace - PrefetchURLLoaderService::PrefetchURLLoaderService( scoped_refptr<URLLoaderFactoryGetter> factory_getter) : loader_factory_getter_(std::move(factory_getter)) {} @@ -114,10 +44,7 @@ frame_tree_node_id, std::move(request))); return; } - service_bindings_.AddBinding( - std::make_unique<PrefetchURLLoaderFactory>(this, loader_factory_getter_, - frame_tree_node_id), - std::move(request)); + service_bindings_.AddBinding(this, std::move(request), frame_tree_node_id); } void PrefetchURLLoaderService::CreateLoaderAndStart( @@ -154,6 +81,49 @@ PrefetchURLLoaderService::~PrefetchURLLoaderService() = default; +void PrefetchURLLoaderService::GetFactory( + network::mojom::URLLoaderFactoryRequest request) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + loader_factory_bindings_.AddBinding(this, std::move(request), + service_bindings_.dispatch_context()); +} + +void PrefetchURLLoaderService::CreateLoaderAndStart( + network::mojom::URLLoaderRequest request, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest& resource_request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); + if (!network_loader_factory_ || network_loader_factory_.encountered_error()) { + loader_factory_getter_->GetNetworkFactory()->Clone( + mojo::MakeRequest(&network_loader_factory_)); + } + int frame_tree_node_id = loader_factory_bindings_.dispatch_context(); + CreateLoaderAndStart( + std::move(request), routing_id, request_id, options, resource_request, + std::move(client), traffic_annotation, + // NOTE: This should be fine in most cases, where the loader + // factory may become invalid if Network Service process is killed + // and restarted. The load can just fail in the case here, but if + // we want to be extra sure this should create a SharedURLLoaderFactory + // that internally holds a ref to the URLLoaderFactoryGetter so that + // it can re-obtain the factory if necessary. + base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>( + network_loader_factory_.get()), + frame_tree_node_id); +} + +void PrefetchURLLoaderService::Clone( + network::mojom::URLLoaderFactoryRequest request) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + loader_factory_bindings_.AddBinding( + this, std::move(request), loader_factory_bindings_.dispatch_context()); +} + std::vector<std::unique_ptr<content::URLLoaderThrottle>> PrefetchURLLoaderService::CreateURLLoaderThrottles( const network::ResourceRequest& request,
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h index 99faf06..eb3964d6 100644 --- a/content/browser/loader/prefetch_url_loader_service.h +++ b/content/browser/loader/prefetch_url_loader_service.h
@@ -11,6 +11,7 @@ #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/strong_binding_set.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/WebKit/public/mojom/loader/prefetch_url_loader_service.mojom.h" namespace net { @@ -26,7 +27,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final : public base::RefCountedThreadSafe<PrefetchURLLoaderService, - BrowserThread::DeleteOnIOThread> { + BrowserThread::DeleteOnIOThread>, + public network::mojom::URLLoaderFactory, + public blink::mojom::PrefetchURLLoaderService { public: // |factory_getter| could be null in non-NetworkService case. // Created on the UI thread. @@ -69,20 +72,40 @@ private: friend class base::DeleteHelper<content::PrefetchURLLoaderService>; friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; - ~PrefetchURLLoaderService(); + ~PrefetchURLLoaderService() override; + + // blink::mojom::PrefetchURLLoaderService: + void GetFactory(network::mojom::URLLoaderFactoryRequest request) override; + + // network::mojom::URLLoaderFactory: + void CreateLoaderAndStart(network::mojom::URLLoaderRequest request, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest& resource_request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag& + traffic_annotation) override; + void Clone(network::mojom::URLLoaderFactoryRequest request) override; // For URLLoaderThrottlesGetter. std::vector<std::unique_ptr<content::URLLoaderThrottle>> CreateURLLoaderThrottles(const network::ResourceRequest& request, int frame_tree_node_id); - mojo::StrongBindingSet<blink::mojom::PrefetchURLLoaderService> + mojo::BindingSet<blink::mojom::PrefetchURLLoaderService, + int /* frame_tree_node_id */> service_bindings_; scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_; ResourceContext* resource_context_ = nullptr; scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + network::mojom::URLLoaderFactoryPtr network_loader_factory_; + mojo::BindingSet<network::mojom::URLLoaderFactory, + int /* frame_tree_node_id */> + loader_factory_bindings_; + base::RepeatingClosure prefetch_load_callback_for_testing_; DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoaderService);
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 729100d..a2f7c3c 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -530,7 +530,6 @@ std::unique_ptr<ResourceHandler> ResourceDispatcherHostImpl::MaybeInterceptAsStream( - const base::FilePath& plugin_path, net::URLRequest* request, network::ResourceResponse* response, std::string* payload) { @@ -539,9 +538,8 @@ const std::string& mime_type = response->head.mime_type; GURL origin; - if (!delegate_ || - !delegate_->ShouldInterceptResourceAsStream( - request, plugin_path, mime_type, &origin, payload)) { + if (!delegate_ || !delegate_->ShouldInterceptResourceAsStream( + request, mime_type, &origin, payload)) { return std::unique_ptr<ResourceHandler>(); }
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 264ae27..aeb1bcf 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -225,15 +225,13 @@ // resource response to another application (e.g. a web page) without being // handled by the browser itself. If the request should be intercepted as a // stream, a StreamResourceHandler is returned which provides access to the - // response. |plugin_path| is the path to the plugin which is handling the - // URL request. This may be empty if there is no plugin handling the request. + // response. // // This function must be called after the ResourceRequestInfo has been created // and associated with the request. If |payload| is set to a non-empty value, // the caller must send it to the old resource handler instead of cancelling // it. virtual std::unique_ptr<ResourceHandler> MaybeInterceptAsStream( - const base::FilePath& plugin_path, net::URLRequest* request, network::ResourceResponse* response, std::string* payload);
diff --git a/content/browser/media/android/media_resource_getter_impl.cc b/content/browser/media/android/media_resource_getter_impl.cc index ca8226d2..e9b8a42 100644 --- a/content/browser/media/android/media_resource_getter_impl.cc +++ b/content/browser/media/android/media_resource_getter_impl.cc
@@ -23,6 +23,7 @@ #include "jni/MediaResourceGetter_jni.h" #include "media/base/android/media_url_interceptor.h" #include "net/base/auth.h" +#include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_store.h" #include "net/http/http_auth.h" #include "net/http/http_transaction_factory.h" @@ -36,13 +37,20 @@ namespace content { -static void ReturnResultOnUIThread( +static void ReturnStringResultOnUIThread( base::OnceCallback<void(const std::string&)> callback, const std::string& result) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::BindOnce(std::move(callback), result)); } +static void ReturnCookieListResultOnUIThread( + net::CookieStore::GetCookieListCallback callback, + const net::CookieList& result) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(callback), result)); +} + static void RequestPlaformPathFromFileSystemURL( const GURL& url, int render_process_id, @@ -58,9 +66,9 @@ base::FilePath data_storage_path; PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path); if (data_storage_path.IsParent(platform_path)) - ReturnResultOnUIThread(std::move(callback), platform_path.value()); + ReturnStringResultOnUIThread(std::move(callback), platform_path.value()); else - ReturnResultOnUIThread(std::move(callback), std::string()); + ReturnStringResultOnUIThread(std::move(callback), std::string()); } // Posts a task to the UI thread to run the callback function. @@ -130,7 +138,7 @@ // Called by MediaResourceGetterImpl to start getting cookies for a URL. void RequestCookies(const GURL& url, const GURL& site_for_cookies, - media::MediaResourceGetter::GetCookieCB callback); + net::CookieStore::GetCookieListCallback callback); // Returns the task runner that all methods should be called. scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const; @@ -141,7 +149,7 @@ void CheckPolicyForCookies(const GURL& url, const GURL& site_for_cookies, - media::MediaResourceGetter::GetCookieCB callback, + net::CookieStore::GetCookieListCallback callback, const net::CookieList& cookie_list); // Context getter used to get the CookieStore and auth cache. @@ -196,19 +204,19 @@ void MediaResourceGetterTask::RequestCookies( const GURL& url, const GURL& site_for_cookies, - media::MediaResourceGetter::GetCookieCB callback) { + net::CookieStore::GetCookieListCallback callback) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (!policy->CanAccessDataForOrigin(render_process_id_, url)) { - std::move(callback).Run(std::string()); + std::move(callback).Run(net::CookieList()); return; } net::CookieStore* cookie_store = context_getter_->GetURLRequestContext()->cookie_store(); if (!cookie_store) { - std::move(callback).Run(std::string()); + std::move(callback).Run(net::CookieList()); return; } @@ -225,18 +233,14 @@ void MediaResourceGetterTask::CheckPolicyForCookies( const GURL& url, const GURL& site_for_cookies, - media::MediaResourceGetter::GetCookieCB callback, + net::CookieStore::GetCookieListCallback callback, const net::CookieList& cookie_list) { if (GetContentClient()->browser()->AllowGetCookie( url, site_for_cookies, cookie_list, resource_context_, render_process_id_, render_frame_id_)) { - net::CookieStore* cookie_store = - context_getter_->GetURLRequestContext()->cookie_store(); - net::CookieOptions options; - options.set_include_httponly(); - cookie_store->GetCookiesWithOptionsAsync(url, options, std::move(callback)); + std::move(callback).Run(cookie_list); } else { - std::move(callback).Run(std::string()); + std::move(callback).Run(net::CookieList()); } } @@ -276,14 +280,14 @@ scoped_refptr<MediaResourceGetterTask> task = new MediaResourceGetterTask( browser_context_, render_process_id_, render_frame_id_); - GetCookieCB cb = + net::CookieStore::GetCookieListCallback cb = base::BindOnce(&MediaResourceGetterImpl::GetCookiesCallback, weak_factory_.GetWeakPtr(), std::move(callback)); task->GetTaskRunner()->PostTask( FROM_HERE, - base::BindOnce(&MediaResourceGetterTask::RequestCookies, task, url, - site_for_cookies, - base::BindOnce(&ReturnResultOnUIThread, std::move(cb)))); + base::BindOnce( + &MediaResourceGetterTask::RequestCookies, task, url, site_for_cookies, + base::BindOnce(&ReturnCookieListResultOnUIThread, std::move(cb)))); } void MediaResourceGetterImpl::GetAuthCredentialsCallback( @@ -293,10 +297,12 @@ std::move(callback).Run(credentials.username(), credentials.password()); } -void MediaResourceGetterImpl::GetCookiesCallback(GetCookieCB callback, - const std::string& cookies) { +void MediaResourceGetterImpl::GetCookiesCallback( + GetCookieCB callback, + const net::CookieList& cookie_list) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::move(callback).Run(cookies); + std::string cookie_line = net::CanonicalCookie::BuildCookieLine(cookie_list); + std::move(callback).Run(std::move(cookie_line)); } void MediaResourceGetterImpl::GetPlatformPathFromURL(
diff --git a/content/browser/media/android/media_resource_getter_impl.h b/content/browser/media/android/media_resource_getter_impl.h index abab2da..c2258c03 100644 --- a/content/browser/media/android/media_resource_getter_impl.h +++ b/content/browser/media/android/media_resource_getter_impl.h
@@ -64,7 +64,8 @@ const net::AuthCredentials& credentials); // Called when GetCookies() finishes. - void GetCookiesCallback(GetCookieCB callback, const std::string& cookies); + void GetCookiesCallback(GetCookieCB callback, + const net::CookieList& cookie_list); // Called when GetPlatformPathFromFileSystemURL() finishes. void GetPlatformPathCallback(GetPlatformPathCB callback,
diff --git a/content/browser/payments/payment_app_info_fetcher.cc b/content/browser/payments/payment_app_info_fetcher.cc index 2277cd5..ba2c16ec 100644 --- a/content/browser/payments/payment_app_info_fetcher.cc +++ b/content/browser/payments/payment_app_info_fetcher.cc
@@ -79,24 +79,24 @@ } for (const auto& frame : *provider_hosts) { + // Find out the render frame host registering the payment app. RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl::FromID(frame.first, frame.second); - if (!render_frame_host) - continue; - - WebContentsImpl* context_web_content = static_cast<WebContentsImpl*>( - WebContents::FromRenderFrameHost(render_frame_host)); - if (!context_web_content || context_web_content->IsHidden() || + if (!render_frame_host || context_url.spec().compare( - context_web_content->GetLastCommittedURL().spec()) != 0) { + render_frame_host->GetLastCommittedURL().spec()) != 0) { continue; } // Get the main frame since web app manifest is only available in the main // frame's document by definition. The main frame's document must come from // the same origin. + RenderFrameHostImpl* top_level_render_frame_host = render_frame_host; + while (top_level_render_frame_host->GetParent() != nullptr) { + top_level_render_frame_host = top_level_render_frame_host->GetParent(); + } WebContentsImpl* top_level_web_content = static_cast<WebContentsImpl*>( - WebContents::FromRenderFrameHost(context_web_content->GetMainFrame())); + WebContents::FromRenderFrameHost(top_level_render_frame_host)); if (!top_level_web_content || top_level_web_content->IsHidden() || !url::IsSameOriginWith(context_url, top_level_web_content->GetLastCommittedURL())) {
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc index 63becba0..4708884 100644 --- a/content/browser/renderer_host/clipboard_host_impl.cc +++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -32,7 +32,6 @@ #include "url/gurl.h" namespace content { - namespace { void ReleaseSharedMemoryPixels(void* addr, void* context) { @@ -40,6 +39,46 @@ DCHECK_EQ(MOJO_RESULT_OK, result); } +void OnReadAndEncodeImageFinished( + scoped_refptr<ChromeBlobStorageContext> blob_storage_context, + std::vector<uint8_t> png_data, + ClipboardHostImpl::ReadImageCallback callback) { + // |blob_storage_context| must be accessed only on the IO thread. + DCHECK_CURRENTLY_ON(BrowserThread::IO); + blink::mojom::SerializedBlobPtr blob; + if (png_data.size() < std::numeric_limits<uint32_t>::max()) { + std::unique_ptr<content::BlobHandle> blob_handle = + blob_storage_context->CreateMemoryBackedBlob( + reinterpret_cast<char*>(png_data.data()), png_data.size(), ""); + if (blob_handle) { + std::string blob_uuid = blob_handle->GetUUID(); + blob = blink::mojom::SerializedBlob::New( + blob_uuid, ui::Clipboard::kMimeTypePNG, + static_cast<int64_t>(png_data.size()), + blob_handle->PassBlob().PassInterface()); + } + } + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(callback), std::move(blob))); +} + +void ReadAndEncodeImage( + scoped_refptr<ChromeBlobStorageContext> blob_storage_context, + const SkBitmap& bitmap, + ClipboardHostImpl::ReadImageCallback callback) { + std::vector<uint8_t> png_data; + if (!gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(callback), nullptr)); + return; + } + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::BindOnce(&OnReadAndEncodeImageFinished, + std::move(blob_storage_context), std::move(png_data), + std::move(callback))); +} + } // namespace ClipboardHostImpl::ClipboardHostImpl( @@ -159,51 +198,16 @@ SkBitmap bitmap = clipboard_->ReadImage(clipboard_type); + if (bitmap.isNull()) { + std::move(callback).Run(nullptr); + return; + } base::PostTaskWithTraits( FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce(&ClipboardHostImpl::ReadAndEncodeImage, - base::Unretained(this), bitmap, std::move(callback))); -} - -void ClipboardHostImpl::ReadAndEncodeImage(const SkBitmap& bitmap, - ReadImageCallback callback) { - if (!bitmap.isNull()) { - std::vector<uint8_t> png_data; - if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&ClipboardHostImpl::OnReadAndEncodeImageFinished, - base::Unretained(this), std::move(png_data), - std::move(callback))); - return; - } - } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(std::move(callback), nullptr)); -} - -void ClipboardHostImpl::OnReadAndEncodeImageFinished( - std::vector<uint8_t> png_data, - ReadImageCallback callback) { - // |blob_storage_context_| must be accessed only on the IO thread. - DCHECK_CURRENTLY_ON(BrowserThread::IO); - blink::mojom::SerializedBlobPtr blob; - if (png_data.size() < std::numeric_limits<uint32_t>::max()) { - std::unique_ptr<content::BlobHandle> blob_handle = - blob_storage_context_->CreateMemoryBackedBlob( - reinterpret_cast<char*>(png_data.data()), png_data.size(), ""); - if (blob_handle) { - std::string blob_uuid = blob_handle->GetUUID(); - blob = blink::mojom::SerializedBlob::New( - blob_uuid, ui::Clipboard::kMimeTypePNG, - static_cast<int64_t>(png_data.size()), - blob_handle->PassBlob().PassInterface()); - } - } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(std::move(callback), std::move(blob))); + base::BindOnce(&ReadAndEncodeImage, blob_storage_context_, + std::move(bitmap), std::move(callback))); } void ClipboardHostImpl::ReadCustomData(ui::ClipboardType clipboard_type,
diff --git a/content/browser/renderer_host/clipboard_host_impl.h b/content/browser/renderer_host/clipboard_host_impl.h index 68c18c4c..525fe113 100644 --- a/content/browser/renderer_host/clipboard_host_impl.h +++ b/content/browser/renderer_host/clipboard_host_impl.h
@@ -51,10 +51,6 @@ explicit ClipboardHostImpl( scoped_refptr<ChromeBlobStorageContext> blob_storage_context); - void ReadAndEncodeImage(const SkBitmap& bitmap, ReadImageCallback callback); - void OnReadAndEncodeImageFinished(std::vector<uint8_t> png_data, - ReadImageCallback callback); - // content::mojom::ClipboardHost void GetSequenceNumber(ui::ClipboardType clipboard_type, GetSequenceNumberCallback callback) override;
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index ed449be..5b3a8ed 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -272,20 +272,29 @@ pending_local_surface_id_ = new_pending_local_surface_id; pending_surface_dip_size_ = new_pending_dip_size; - if (enable_surface_synchronization_ && - client_->DelegatedFrameHostIsVisible() && - (!primary_surface_id || - primary_surface_id->local_surface_id() != pending_local_surface_id_)) { - current_frame_size_in_dip_ = pending_surface_dip_size_; - - viz::SurfaceId surface_id(frame_sink_id_, pending_local_surface_id_); - client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface( - surface_id, current_frame_size_in_dip_, GetGutterColor(), - deadline_policy); - if (compositor_ && !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableResizeLock)) { - compositor_->OnChildResizing(); + if (enable_surface_synchronization_) { + if (!client_->DelegatedFrameHostIsVisible()) { + if (HasFallbackSurface()) { + client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId( + viz::SurfaceId()); + } + return; } + + if (!primary_surface_id || + primary_surface_id->local_surface_id() != pending_local_surface_id_) { + current_frame_size_in_dip_ = pending_surface_dip_size_; + + viz::SurfaceId surface_id(frame_sink_id_, pending_local_surface_id_); + client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface( + surface_id, current_frame_size_in_dip_, GetGutterColor(), + deadline_policy); + if (compositor_ && !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableResizeLock)) { + compositor_->OnChildResizing(); + } + } + // Input throttling and guttering are handled differently when surface // synchronization is enabled so exit early here. return; @@ -547,7 +556,7 @@ } void DelegatedFrameHost::EvictDelegatedFrame() { - if (!HasFallbackSurface()) + if (!HasSavedFrame()) return; std::vector<viz::SurfaceId> surface_ids = { @@ -556,8 +565,10 @@ GetHostFrameSinkManager()->EvictSurfaces(surface_ids); if (enable_surface_synchronization_) { - client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId( - viz::SurfaceId()); + if (HasFallbackSurface()) { + client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId( + viz::SurfaceId()); + } } else { client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent(); resize_lock_.reset();
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 8cf370ed..9cc395d1 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -972,6 +972,14 @@ if (!repaint_ack_pending_ && !resize_ack_pending_) return; + // OnResizeOrRepaintACK posts a task to the default TaskRunner in auto-resize, + // which is not the one that we pump in this nested loop, causing unexpected + // behavior. It very well may be safe to do that post task to the TaskRunner + // from ui::WindowResizeHelperMac (which we pump), but don't do that until + // it is known to be safe. + if (auto_resize_enabled_) + return; + if (!view_) return;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index a9ed2c8..2ef69ac 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -353,10 +353,8 @@ : rwhv_mac_(nullptr), wheel_scrolling_mode_(wheel_scrolling_mode), scroll_latching_(wheel_scrolling_mode_ != kWheelScrollingModeNone) { - std::unique_ptr<base::SimpleTestTickClock> mock_clock( - new base::SimpleTestTickClock()); - mock_clock->Advance(base::TimeDelta::FromMilliseconds(100)); - ui::SetEventTickClockForTesting(std::move(mock_clock)); + mock_clock_.Advance(base::TimeDelta::FromMilliseconds(100)); + ui::SetEventTickClockForTesting(&mock_clock_); SetFeatureList(); mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages); @@ -452,6 +450,8 @@ base::test::ScopedFeatureList vsync_feature_list_; base::test::ScopedFeatureList feature_list_; + base::SimpleTestTickClock mock_clock_; + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMacTest); };
diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc index 373287054..fdf5de65 100644 --- a/content/browser/service_worker/service_worker_client_utils.cc +++ b/content/browser/service_worker/service_worker_client_utils.cc
@@ -114,7 +114,7 @@ RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl::FromID(render_process_id, render_frame_id); if (!render_frame_host) - return blink::mojom::ServiceWorkerClientInfo::New(); + return nullptr; // TODO(mlamouri,michaeln): it is possible to end up collecting information // for a frame that is actually being navigated and isn't exactly what we are @@ -141,7 +141,7 @@ WebContents::FromRenderFrameHost(render_frame_host)); if (!render_frame_host || !web_contents) - return blink::mojom::ServiceWorkerClientInfo::New(); + return nullptr; FrameTreeNode* frame_tree_node = render_frame_host->frame_tree_node(); @@ -304,12 +304,13 @@ blink::mojom::ServiceWorkerClientInfoPtr info = GetWindowClientInfoOnUI( std::get<0>(it), std::get<1>(it), std::get<2>(it), std::get<3>(it)); - // If the request to the provider_host returned an invalid + // If the request to the provider_host returned a null // ServiceWorkerClientInfo, that means that it wasn't possible to associate // it with a valid RenderFrameHost. It might be because the frame was killed // or navigated in between. - if (info->client_uuid.empty()) + if (!info) continue; + DCHECK(!info->client_uuid.empty()); // We can get info for a frame that was navigating end ended up with a // different URL than expected. In such case, we should make sure to not @@ -535,14 +536,14 @@ if (!context) { std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT, - blink::mojom::ServiceWorkerClientInfo::New()); + nullptr /* client_info */); return; } if (render_process_id == ChildProcessHost::kInvalidUniqueID && render_frame_id == MSG_ROUTING_NONE) { std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED, - blink::mojom::ServiceWorkerClientInfo::New()); + nullptr /* client_info */); return; } @@ -565,8 +566,7 @@ // If here, it means that no provider_host was found, in which case, the // renderer should still be informed that the window was opened. - std::move(callback).Run(SERVICE_WORKER_OK, - blink::mojom::ServiceWorkerClientInfo::New()); + std::move(callback).Run(SERVICE_WORKER_OK, nullptr /* client_info */); } } // namespace service_worker_client_utils
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index f5cabf1..d2a1040 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -335,14 +335,10 @@ StatusCallback callback, int source_service_worker_provider_id, blink::mojom::ServiceWorkerClientInfoPtr source_client_info) { - DCHECK(source_service_worker_provider_id != kInvalidServiceWorkerProviderId || - source_client_info); - if (source_service_worker_provider_id == kInvalidServiceWorkerProviderId) { - DCHECK(source_client_info); - if (source_client_info->client_uuid.empty()) { - std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED); - return; - } + if (source_service_worker_provider_id == kInvalidServiceWorkerProviderId && + !source_client_info) { + std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED); + return; } // If not enough time is left to actually process the event don't even
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h index bf35439..9f669ef 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.h +++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -150,9 +150,8 @@ const url::Origin& source_origin, int source_provider_id, StatusCallback callback); - // |source_service_worker_provider_id| and |source_client_info| are mutually - // exclusive. |source_service_worker_provider_id| is passed if the message - // source is a service worker, and otherwise |source_client_info| is passed. + // A valid |source_service_worker_provider_id| is passed if the message source + // is a service worker, and otherwise |source_client_info| is passed. void DispatchExtendableMessageEventInternal( scoped_refptr<ServiceWorkerVersion> worker, blink::TransferableMessage message,
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 82ceb9d..2417abc 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -191,17 +191,13 @@ ServiceWorkerStatusCode status, blink::mojom::ServiceWorkerClientInfoPtr client_info) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (status != SERVICE_WORKER_OK) { - std::move(callback).Run( - nullptr /* client */, - std::string("Something went wrong while trying to open the window.")); - return; + const bool success = (status == SERVICE_WORKER_OK); + base::Optional<std::string> error_msg; + if (!success) { + DCHECK(!client_info); + error_msg.emplace("Something went wrong while trying to open the window."); } - - DCHECK(client_info); - std::move(callback).Run(std::move(client_info), - base::nullopt /* error_msg */); + std::move(callback).Run(success, std::move(client_info), error_msg); } void DidShowPaymentHandlerWindow( @@ -218,7 +214,7 @@ render_process_id, render_frame_id); } else { OnOpenWindowFinished(std::move(callback), SERVICE_WORKER_ERROR_FAILED, - blink::mojom::ServiceWorkerClientInfo::New()); + nullptr /* client_info */); } } @@ -236,12 +232,13 @@ ServiceWorkerStatusCode status, blink::mojom::ServiceWorkerClientInfoPtr client) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (status != SERVICE_WORKER_OK) { - std::move(callback).Run(nullptr /* client */, - "Cannot navigate to URL: " + url.spec()); - return; + const bool success = (status == SERVICE_WORKER_OK); + base::Optional<std::string> error_msg; + if (!success) { + DCHECK(!client); + error_msg.emplace("Cannot navigate to URL: " + url.spec()); } - std::move(callback).Run(std::move(client), base::nullopt /* error_msg */); + std::move(callback).Run(success, std::move(client), error_msg); } } // namespace @@ -1119,7 +1116,7 @@ GetClientCallback callback) { if (!context_) { // The promise will be resolved to 'undefined'. - std::move(callback).Run(blink::mojom::ServiceWorkerClientInfo::New()); + std::move(callback).Run(nullptr); return; } ServiceWorkerProviderHost* provider_host = @@ -1127,7 +1124,7 @@ if (!provider_host || provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) { // The promise will be resolved to 'undefined'. - std::move(callback).Run(blink::mojom::ServiceWorkerClientInfo::New()); + std::move(callback).Run(nullptr); return; } service_worker_client_utils::GetClient(provider_host, std::move(callback)); @@ -1145,7 +1142,7 @@ // Just respond failure if we are shutting down. if (!context_) { std::move(callback).Run( - nullptr /* client */, + false /* success */, nullptr /* client */, std::string("The service worker system is shutting down.")); return; } @@ -1195,7 +1192,7 @@ NavigateClientCallback callback) { if (!context_) { std::move(callback).Run( - nullptr /* client */, + false /* success */, nullptr /* client */, std::string("The service worker system is shutting down.")); return; } @@ -1214,7 +1211,7 @@ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( embedded_worker_->process_id(), url)) { std::move(callback).Run( - nullptr /* client */, + false /* success */, nullptr /* client */, "The service worker is not allowed to access URL: " + url.spec()); return; } @@ -1222,13 +1219,13 @@ ServiceWorkerProviderHost* provider_host = context_->GetProviderHostByClientID(client_uuid); if (!provider_host) { - std::move(callback).Run(nullptr /* client */, + std::move(callback).Run(false /* success */, nullptr /* client */, std::string("The client was not found.")); return; } if (provider_host->active_version() != this) { std::move(callback).Run( - nullptr /* client */, + false /* success */, nullptr /* client */, std::string( "This service worker is not the client's active service worker.")); return; @@ -1300,7 +1297,7 @@ // Just respond failure if we are shutting down. if (!context_) { std::move(callback).Run( - nullptr /* client */, + false /* success */, nullptr /* client */, std::string("The service worker system is shutting down.")); return; } @@ -1323,7 +1320,7 @@ // filtered out by Blink. if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( embedded_worker_->process_id(), url)) { - std::move(callback).Run(nullptr /* client */, + std::move(callback).Run(false /* success */, nullptr /* client */, url.spec() + " cannot be opened."); return; }
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 3107f25..cfb2f80 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -137,9 +137,9 @@ // Returns true, if the given cookie exists in the cookie store. bool ContainsCookie() { get_cookie_success_ = false; - cookie_store_->GetCookiesWithOptionsAsync( + cookie_store_->GetCookieListWithOptionsAsync( kOrigin1, net::CookieOptions(), - base::BindOnce(&RemoveCookieTester::GetCookieCallback, + base::BindOnce(&RemoveCookieTester::GetCookieListCallback, base::Unretained(this))); await_completion_.BlockUntilNotified(); return get_cookie_success_; @@ -154,11 +154,13 @@ } private: - void GetCookieCallback(const std::string& cookies) { - if (cookies == "A=1") { + void GetCookieListCallback(const net::CookieList& cookie_list) { + std::string cookie_line = + net::CanonicalCookie::BuildCookieLine(cookie_list); + if (cookie_line == "A=1") { get_cookie_success_ = true; } else { - EXPECT_EQ("", cookies); + EXPECT_EQ("", cookie_line); get_cookie_success_ = false; } await_completion_.Notify();
diff --git a/content/common/browser_plugin/browser_plugin_messages.h b/content/common/browser_plugin/browser_plugin_messages.h index a02b27f..80b3ab8 100644 --- a/content/common/browser_plugin/browser_plugin_messages.h +++ b/content/common/browser_plugin/browser_plugin_messages.h
@@ -165,6 +165,14 @@ // ----------------------------------------------------------------------------- // These messages are from the browser process to the embedder. +// Indicates that an attach request has completed. The provided +// |child_local_surface_id| is used as the seed for the +// ParentLocalSurfaceIdAllocator. +IPC_MESSAGE_CONTROL2( + BrowserPluginMsg_Attach_ACK, + int /* browser_plugin_instance_id */, + base::Optional<viz::LocalSurfaceId> /* child_local_surface_id */) + // When the guest crashes, the browser process informs the embedder through this // message. IPC_MESSAGE_CONTROL1(BrowserPluginMsg_GuestGone,
diff --git a/content/public/browser/resource_dispatcher_host_delegate.cc b/content/public/browser/resource_dispatcher_host_delegate.cc index f6f79eef..f6e3803c 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.cc +++ b/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -48,7 +48,6 @@ bool ResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( net::URLRequest* request, - const base::FilePath& plugin_path, const std::string& mime_type, GURL* origin, std::string* payload) {
diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h index 1599163..9b14331 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.h +++ b/content/public/browser/resource_dispatcher_host_delegate.h
@@ -81,9 +81,7 @@ ResourceRequestInfo* info); // Returns true and sets |origin| if a Stream should be created for the - // resource. |plugin_path| is the plugin which will be used to handle the - // request (if the stream will be rendered in a BrowserPlugin). It may be - // empty. If true is returned, a new Stream will be created and + // resource. If true is returned, a new Stream will be created and // OnStreamCreated() will be called with a StreamHandle instance for the // Stream. The handle contains the URL for reading the Stream etc. The // Stream's origin will be set to |origin|. @@ -93,7 +91,6 @@ // renderer process. virtual bool ShouldInterceptResourceAsStream( net::URLRequest* request, - const base::FilePath& plugin_path, const std::string& mime_type, GURL* origin, std::string* payload);
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index d850d931..b2e5854c 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -120,6 +120,7 @@ bool handled = true; IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message) IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus) + IPC_MESSAGE_HANDLER(BrowserPluginMsg_Attach_ACK, OnAttachACK) IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone) IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestReady, OnGuestReady) IPC_MESSAGE_HANDLER(BrowserPluginMsg_ResizeDueToAutoResize, @@ -192,8 +193,6 @@ browser_plugin_instance_id_, attach_params)); - attached_ = true; - // Post an update event to the associated accessibility object. auto* render_frame = RenderFrameImpl::FromRoutingID(render_frame_routing_id()); @@ -207,7 +206,6 @@ } sent_resize_params_ = base::nullopt; - WasResized(); } void BrowserPlugin::Detach() { @@ -222,6 +220,10 @@ new BrowserPluginHostMsg_Detach(browser_plugin_instance_id_)); } +const viz::LocalSurfaceId& BrowserPlugin::GetLocalSurfaceId() const { + return parent_local_surface_id_allocator_.last_known_local_surface_id(); +} + #if defined(USE_AURA) void BrowserPlugin::CreateMusWindowAndEmbed( const base::UnguessableToken& embed_token) { @@ -237,8 +239,8 @@ DCHECK(renderer_window_tree_client); mus_embedded_frame_ = renderer_window_tree_client->CreateMusEmbeddedFrame(this, embed_token); - if (attached() && local_surface_id_.is_valid()) { - mus_embedded_frame_->SetWindowBounds(local_surface_id_, + if (attached() && GetLocalSurfaceId().is_valid()) { + mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(), FrameRectInPixels()); } } @@ -256,11 +258,12 @@ sent_resize_params_->screen_info != pending_resize_params_.screen_info; if (synchronized_params_changed) - local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); + parent_local_surface_id_allocator_.GenerateId(); if (enable_surface_synchronization_ && frame_sink_id_.is_valid()) { compositing_helper_->SetPrimarySurfaceId( - viz::SurfaceId(frame_sink_id_, local_surface_id_), frame_rect().size()); + viz::SurfaceId(frame_sink_id_, GetLocalSurfaceId()), + frame_rect().size()); } bool position_changed = @@ -273,7 +276,7 @@ BrowserPluginManager::Get()->Send( new BrowserPluginHostMsg_UpdateResizeParams( browser_plugin_instance_id_, frame_rect(), screen_info(), - auto_size_sequence_number(), local_surface_id_)); + auto_size_sequence_number(), GetLocalSurfaceId())); } if (delegate_ && size_changed) @@ -284,7 +287,7 @@ #if defined(USE_AURA) if (features::IsMusEnabled() && mus_embedded_frame_) { - mus_embedded_frame_->SetWindowBounds(local_surface_id_, + mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(), FrameRectInPixels()); } #endif @@ -300,6 +303,15 @@ render_view->GetWebView()->AdvanceFocus(reverse); } +void BrowserPlugin::OnAttachACK( + int browser_plugin_instance_id, + const base::Optional<viz::LocalSurfaceId>& child_local_surface_id) { + attached_ = true; + if (child_local_surface_id) + parent_local_surface_id_allocator_.Reset(*child_local_surface_id); + WasResized(); +} + void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) { guest_crashed_ = true; compositing_helper_->ChildFrameGone(frame_rect().size(),
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h index e7b021d..bf83046 100644 --- a/content/renderer/browser_plugin/browser_plugin.h +++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -86,6 +86,9 @@ // currently attached to, if any. void Detach(); + // Returns the last allocated LocalSurfaceId. + const viz::LocalSurfaceId& GetLocalSurfaceId() const; + void WasResized(); // Returns whether a message should be forwarded to BrowserPlugin. @@ -183,6 +186,9 @@ // IPC message handlers. // Please keep in alphabetical order. void OnAdvanceFocus(int instance_id, bool reverse); + void OnAttachACK( + int browser_plugin_instance_id, + const base::Optional<viz::LocalSurfaceId>& child_local_surface_id); void OnGuestGone(int instance_id); void OnGuestReady(int instance_id, const viz::FrameSinkId& frame_sink_id); void OnResizeDueToAutoResize(int browser_plugin_instance_id, @@ -242,7 +248,6 @@ std::vector<EditCommand> edit_commands_; viz::FrameSinkId frame_sink_id_; - viz::LocalSurfaceId local_surface_id_; viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_; bool enable_surface_synchronization_ = false;
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index 3f39647..c50636b 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -424,7 +424,6 @@ blink::mojom::ServiceWorkerErrorType error, const base::Optional<std::string>& error_msg) { if (error != blink::mojom::ServiceWorkerErrorType::kNone) { - DCHECK(error_msg); callbacks->OnError(blink::WebServiceWorkerError( error, blink::WebString::FromUTF8(*error_msg))); return; @@ -437,7 +436,7 @@ std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks, blink::mojom::ServiceWorkerClientInfoPtr client) { std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client; - if (!client->client_uuid.empty()) { + if (client) { web_client = std::make_unique<blink::WebServiceWorkerClientInfo>( ToWebServiceWorkerClientInfo(std::move(client))); } @@ -456,9 +455,10 @@ void DidOpenWindow( std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks, + bool success, blink::mojom::ServiceWorkerClientInfoPtr client, const base::Optional<std::string>& error_msg) { - if (error_msg) { + if (!success) { DCHECK(!client); callbacks->OnError(blink::WebServiceWorkerError( blink::mojom::ServiceWorkerErrorType::kNavigation, @@ -466,9 +466,8 @@ return; } - DCHECK(client); std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client; - if (!client->client_uuid.empty()) { + if (client) { web_client = std::make_unique<blink::WebServiceWorkerClientInfo>( ToWebServiceWorkerClientInfo(std::move(client))); } @@ -478,13 +477,12 @@ void DidFocusClient( std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks, blink::mojom::ServiceWorkerClientInfoPtr client) { - if (!client || client->client_uuid.empty()) { + if (!client) { callbacks->OnError(blink::WebServiceWorkerError( blink::mojom::ServiceWorkerErrorType::kNotFound, "The client was not found.")); return; } - auto web_client = std::make_unique<blink::WebServiceWorkerClientInfo>( ToWebServiceWorkerClientInfo(std::move(client))); callbacks->OnSuccess(std::move(web_client)); @@ -492,9 +490,10 @@ void DidNavigateClient( std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks, + bool success, blink::mojom::ServiceWorkerClientInfoPtr client, const base::Optional<std::string>& error_msg) { - if (error_msg) { + if (!success) { DCHECK(!client); callbacks->OnError(blink::WebServiceWorkerError( blink::mojom::ServiceWorkerErrorType::kNavigation, @@ -502,9 +501,8 @@ return; } - DCHECK(client); std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client; - if (!client->client_uuid.empty()) { + if (client) { web_client = std::make_unique<blink::WebServiceWorkerClientInfo>( ToWebServiceWorkerClientInfo(std::move(client))); }
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 473d701..fd70738 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -122,3 +122,6 @@ bug=809868) self.Flaky('Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing', ['android'], bug=810006) + + self.Fail('Pixel_CSSFilterEffects', ['mac'], bug=815045) + self.Fail('Pixel_CSSFilterEffects_NoOverlays', ['mac'], bug=815045)
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 254b80f7..7424f4b 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -643,12 +643,12 @@ 'filter_effects.html', base_name + '_CSSFilterEffects', test_rect=[0, 0, 300, 300], - revision=7), + revision=8), PixelTestPage( 'filter_effects.html', base_name + '_CSSFilterEffects_NoOverlays', test_rect=[0, 0, 300, 300], - revision=8, + revision=9, tolerance=10, browser_args=no_overlays_args),
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 35cdc87..6937c933 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -18016,7 +18016,13 @@ } } - GLenum compatibility_internal_format = internal_format; + // First lookup compatibility format via texture manager for swizzling legacy + // LUMINANCE/ALPHA formats. + GLenum compatibility_internal_format = + texture_manager()->AdjustTexStorageFormat(feature_info_.get(), + internal_format); + + // Then lookup compatibility format for compressed formats. const CompressedFormatInfo* format_info = GetCompressedFormatInfo(internal_format); if (format_info != nullptr && !format_info->support_check(*feature_info_)) { @@ -18067,6 +18073,7 @@ if (target == GL_TEXTURE_3D) level_depth = std::max(1, level_depth >> 1); } + texture->ApplyFormatWorkarounds(feature_info_.get()); texture->SetImmutable(true); } }
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 7d4b2bfa..36fccf08 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -3315,6 +3315,36 @@ return format; } +// static +GLenum TextureManager::AdjustTexStorageFormat( + const gles2::FeatureInfo* feature_info, + GLenum format) { + // We need to emulate luminance/alpha on core profile only. + if (feature_info->gl_version_info().is_desktop_core_profile) { + switch (format) { + case GL_ALPHA8_EXT: + return GL_R8_EXT; + case GL_LUMINANCE8_EXT: + return GL_R8_EXT; + case GL_LUMINANCE8_ALPHA8_EXT: + return GL_RG8_EXT; + case GL_ALPHA16F_EXT: + return GL_R16F_EXT; + case GL_LUMINANCE16F_EXT: + return GL_R16F_EXT; + case GL_LUMINANCE_ALPHA16F_EXT: + return GL_RG16F_EXT; + case GL_ALPHA32F_EXT: + return GL_R32F_EXT; + case GL_LUMINANCE32F_EXT: + return GL_R32F_EXT; + case GL_LUMINANCE_ALPHA32F_EXT: + return GL_RG32F_EXT; + } + } + return format; +} + void TextureManager::DoTexImage( DecoderTextureState* texture_state, ContextState* state,
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index fe57445c..3fa41a3a 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h
@@ -1092,6 +1092,9 @@ static GLenum AdjustTexFormat(const gles2::FeatureInfo* feature_info, GLenum format); + static GLenum AdjustTexStorageFormat(const gles2::FeatureInfo* feature_info, + GLenum format); + void WorkaroundCopyTexImageCubeMap( DecoderTextureState* texture_state, ContextState* state,
diff --git a/gpu/command_buffer/tests/gl_texture_storage_unittest.cc b/gpu/command_buffer/tests/gl_texture_storage_unittest.cc index 967ddc1..6013b7a 100644 --- a/gpu/command_buffer/tests/gl_texture_storage_unittest.cc +++ b/gpu/command_buffer/tests/gl_texture_storage_unittest.cc
@@ -15,6 +15,63 @@ namespace gpu { +namespace { + +// Blits texture bound to active texture unit to currently bound framebuffer. +// Viewport must be set by caller. +void BlitTexture() { + const GLuint kVertexPositionAttrib = 0; + const GLfloat kQuadVertices[] = {-1.0f, -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 1.0f}; + GLuint buffer_id = 0; + glGenBuffers(1, &buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, buffer_id); + glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, + GL_STATIC_DRAW); + + glEnableVertexAttribArray(kVertexPositionAttrib); + glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); + + GLuint shader_program = glCreateProgram(); + + static const char* kBlitTextureVertexShader = + "precision mediump float;\n" + "attribute vec2 a_position;\n" + "varying mediump vec2 v_uv;\n" + "void main(void) {\n" + " gl_Position = vec4(a_position, 0, 1);\n" + " v_uv = 0.5 * (a_position + vec2(1, 1));\n" + "}\n"; + GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex_shader, 1, &kBlitTextureVertexShader, 0); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + static const char* kBlitTextureFragmentShader = + "uniform sampler2D u_sampler;\n" + "varying mediump vec2 v_uv;\n" + "void main(void) {\n" + " gl_FragColor = texture2D(u_sampler, v_uv);\n" + "}\n"; + GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment_shader, 1, &kBlitTextureFragmentShader, 0); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glBindAttribLocation(shader_program, kVertexPositionAttrib, "a_position"); + + glLinkProgram(shader_program); + glUseProgram(shader_program); + + GLuint sampler_handle = glGetUniformLocation(shader_program, "u_sampler"); + glUniform1i(sampler_handle, 0); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + ASSERT_TRUE(glGetError() == GL_NONE); +} + +} // namespace + class TextureStorageTest : public testing::Test { protected: static const GLsizei kResolution = 64; @@ -31,11 +88,8 @@ glGenFramebuffers(1, &fbo_); glBindFramebuffer(GL_FRAMEBUFFER, fbo_); - glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - tex_, - 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + tex_, 0); const GLubyte* extensions = glGetString(GL_EXTENSIONS); ext_texture_storage_available_ = strstr( @@ -59,9 +113,9 @@ if (!ext_texture_storage_available_) return; - glTexStorage2DEXT(GL_TEXTURE_2D, 2, GL_RGBA8_OES, 2, 2); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 2, 2); - // Mesa dirvers crash without rebinding to FBO. It's why + // Mesa drivers crash without rebinding to FBO. It's why // DISABLE_TEXTURE_STORAGE workaround is introduced. crbug.com/521904 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_, 0); @@ -186,6 +240,108 @@ EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 2, 2, 0, source_pixels, nullptr)); } +TEST_F(TextureStorageTest, LuminanceEmulation) { + if (!ext_texture_storage_available_) + return; + + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 2, 2); + // Mesa drivers crash without rebinding to FBO. It's why + // DISABLE_TEXTURE_STORAGE workaround is introduced. crbug.com/521904 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + tex_, 0); + ASSERT_TRUE(glGetError() == GL_NONE); + + GLuint luminance_tex = 0; + glGenTextures(1, &luminance_tex); + glBindTexture(GL_TEXTURE_2D, luminance_tex); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_LUMINANCE8_EXT, 2, 2); + ASSERT_TRUE(glGetError() == GL_NONE); + + const uint8_t source_data[4] = {1, 1, 1, 1}; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, + source_data); + ASSERT_TRUE(glGetError() == GL_NONE); + + BlitTexture(); + + const uint8_t swizzled_pixel[4] = {1, 1, 1, 255}; + EXPECT_TRUE( + GLTestHelper::CheckPixels(0, 0, 2, 2, 0, swizzled_pixel, nullptr)); +} + +TEST_F(TextureStorageTest, AlphaEmulation) { + if (!ext_texture_storage_available_) + return; + + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 2, 2); + // Mesa drivers crash without rebinding to FBO. It's why + // DISABLE_TEXTURE_STORAGE workaround is introduced. crbug.com/521904 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + tex_, 0); + ASSERT_TRUE(glGetError() == GL_NONE); + + GLuint alpha_tex = 0; + glGenTextures(1, &alpha_tex); + glBindTexture(GL_TEXTURE_2D, alpha_tex); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 2, 2); + ASSERT_TRUE(glGetError() == GL_NONE); + + const uint8_t source_data[4] = {1, 1, 1, 1}; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_ALPHA, GL_UNSIGNED_BYTE, + source_data); + ASSERT_TRUE(glGetError() == GL_NONE); + + BlitTexture(); + + const uint8_t swizzled_pixel[4] = {0, 0, 0, 1}; + EXPECT_TRUE( + GLTestHelper::CheckPixels(0, 0, 2, 2, 0, swizzled_pixel, nullptr)); +} + +TEST_F(TextureStorageTest, LuminanceAlphaEmulation) { + if (!ext_texture_storage_available_) + return; + + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 2, 2); + // Mesa drivers crash without rebinding to FBO. It's why + // DISABLE_TEXTURE_STORAGE workaround is introduced. crbug.com/521904 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + tex_, 0); + ASSERT_TRUE(glGetError() == GL_NONE); + + GLuint luminance_alpha_tex = 0; + glGenTextures(1, &luminance_alpha_tex); + glBindTexture(GL_TEXTURE_2D, luminance_alpha_tex); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_LUMINANCE8_ALPHA8_EXT, 2, 2); + ASSERT_TRUE(glGetError() == GL_NONE); + + const uint8_t source_data[8] = {1, 2, 1, 2, 1, 2, 1, 2}; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_LUMINANCE_ALPHA, + GL_UNSIGNED_BYTE, source_data); + ASSERT_TRUE(glGetError() == GL_NONE); + + BlitTexture(); + + const uint8_t swizzled_pixel[4] = {1, 1, 1, 2}; + EXPECT_TRUE( + GLTestHelper::CheckPixels(0, 0, 2, 2, 0, swizzled_pixel, nullptr)); +} + } // namespace gpu
diff --git a/headless/public/util/testing/generic_url_request_mocks.cc b/headless/public/util/testing/generic_url_request_mocks.cc index 7d4d2e7..62b3fdc 100644 --- a/headless/public/util/testing/generic_url_request_mocks.cc +++ b/headless/public/util/testing/generic_url_request_mocks.cc
@@ -53,13 +53,6 @@ cookies_.push_back(std::move(*cookie)); } -void MockCookieStore::GetCookiesWithOptionsAsync( - const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) { - CHECK(false); -} - void MockCookieStore::GetCookieListWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/headless/public/util/testing/generic_url_request_mocks.h b/headless/public/util/testing/generic_url_request_mocks.h index e1ff2ab..a51b78da 100644 --- a/headless/public/util/testing/generic_url_request_mocks.h +++ b/headless/public/util/testing/generic_url_request_mocks.h
@@ -55,10 +55,6 @@ bool modify_http_only, SetCookiesCallback callback) override; - void GetCookiesWithOptionsAsync(const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) override; - void GetCookieListWithOptionsAsync(const GURL& url, const net::CookieOptions& options, GetCookieListCallback callback) override;
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 61cc98f8..bd41580 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -890,7 +890,8 @@ // Lazily create the main coordinator. if (IsTabSwitcherTabGridEnabled()) { TabGridCoordinator* tabGridCoordinator = - [[TabGridCoordinator alloc] initWithWindow:self.window]; + [[TabGridCoordinator alloc] initWithWindow:self.window + applicationCommandEndpoint:self]; tabGridCoordinator.regularTabModel = self.mainTabModel; tabGridCoordinator.incognitoTabModel = self.otrTabModel; _mainCoordinator = tabGridCoordinator; @@ -1913,7 +1914,7 @@ } } -#pragma mark - TabSwitcherDelegate Implementation +#pragma mark - TabSwitcherDelegate - (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher shouldFinishWithActiveModel:(TabModel*)tabModel { @@ -1924,6 +1925,15 @@ [self finishDismissingStackView]; } +- (id<ToolbarOwner>)tabSwitcherTransitionToolbarOwner { + // Request the view to ensure that the view has been loaded and initialized, + // since it may never have been loaded (or have been swapped out). + [self.currentBVC loadViewIfNeeded]; + return self.currentBVC; +} + +#pragma mark - TabSwitcherDelegate helper methods + - (void)beginDismissingStackViewWithCurrentModel:(TabModel*)tabModel { DCHECK(tabModel == self.mainTabModel || tabModel == self.otrTabModel); @@ -1988,13 +1998,6 @@ _dismissingStackView = NO; } -- (id<ToolbarOwner>)tabSwitcherTransitionToolbarOwner { - // Request the view to ensure that the view has been loaded and initialized, - // since it may never have been loaded (or have been swapped out). - [self.currentBVC loadViewIfNeeded]; - return self.currentBVC; -} - #pragma mark - BrowsingDataCommands - (void)removeBrowsingDataForBrowserState:(ios::ChromeBrowserState*)browserState
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index 8081b25..1f49463 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -20,6 +20,7 @@ ":tab_grid_ui", "//base", "//ios/chrome/browser/tabs", + "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/main", "//ios/chrome/browser/ui/tab_switcher",
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h index 465528b..c5990c3 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h
@@ -7,6 +7,7 @@ #import <Foundation/Foundation.h> +#import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h" #import "ios/chrome/browser/ui/tab_switcher/tab_switcher.h" // An opque adaptor for the TabSwitcher protocol into the TabGrid. @@ -16,6 +17,12 @@ // tab grid, and external code shouldn't depend on them. @interface TabGridAdaptor : NSObject<TabSwitcher> @property(nonatomic, weak) UIViewController* tabGridViewController; +// Dispatcher object this adaptor will expose as the dispacther for the +// TabSwitcher protocol. +@property(nonatomic, weak) + id<ApplicationCommands, BrowserCommands, OmniboxFocuser, ToolbarCommands> + adaptedDispatcher; +@property(nonatomic, weak) TabGridMediator* mediator; @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_ADAPTOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm index 1dc83b1..3bc4ed7 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
@@ -4,6 +4,10 @@ #import "ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h" +#import "ios/chrome/browser/tabs/tab_model.h" +#import "ios/chrome/browser/ui/main/view_controller_swapping.h" +#import "ios/web/public/navigation_manager.h" + #import "base/logging.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -14,51 +18,70 @@ // TabSwitcher properties. @synthesize delegate = _delegate; @synthesize animationDelegate = _animationDelegate; -@synthesize dispatcher = _dispatcher; // Public properties @synthesize tabGridViewController = _tabGridViewController; +@synthesize adaptedDispatcher = _adaptedDispatcher; +@synthesize mediator = _mediator; #pragma mark - TabSwitcher +- (id<ApplicationCommands, BrowserCommands, OmniboxFocuser, ToolbarCommands>) + dispatcher { + return static_cast<id<ApplicationCommands, BrowserCommands, OmniboxFocuser, + ToolbarCommands>>(self.adaptedDispatcher); +} + +- (void)setAnimationDelegate: + (id<TabSwitcherAnimationDelegate>)animationDelegate { + NOTREACHED() + << "The tab grid shouldn't need a tab switcher animation delegate."; + _animationDelegate = nil; +} + - (void)restoreInternalStateWithMainTabModel:(TabModel*)mainModel otrTabModel:(TabModel*)otrModel activeTabModel:(TabModel*)activeModel { - // No-op. + // This is a no-op, but it will be called frequently. } - (void)prepareForDisplayAtSize:(CGSize)size { - // No-op. + NOTREACHED(); } - (void)showWithSelectedTabAnimation { - // No-op. + NOTREACHED(); } - (UIViewController*)viewController { return self.tabGridViewController; } -// Create a new tab in |targetModel| with the url |url| at |position|, using -// page transition |transition|. Implementors are expected to also -// perform an animation from the selected tab in the tab switcher to the -// newly created tab in the content area. Objects adopting this protocol should -// call the following delegate methods: -// |-tabSwitcher:dismissTransitionWillStartWithActiveModel:| -// |-tabSwitcherDismissTransitionDidEnd:| -// to inform the delegate when this animation begins and ends. - (Tab*)dismissWithNewTabAnimationToModel:(TabModel*)targetModel - withURL:(const GURL&)url + withURL:(const GURL&)URL atIndex:(NSUInteger)position transition:(ui::PageTransition)transition { - return nil; + NSUInteger tabIndex = position; + if (position > targetModel.count) + tabIndex = targetModel.count; + + web::NavigationManager::WebLoadParams loadParams(URL); + loadParams.transition_type = transition; + + // Create the new tab. + Tab* tab = [targetModel insertTabWithLoadParams:loadParams + opener:nil + openedByDOM:NO + atIndex:tabIndex + inBackground:NO]; + + // Tell the delegate to display the tab. + [self.delegate tabSwitcher:self shouldFinishWithActiveModel:targetModel]; + + return tab; } -// Updates the OTR (Off The Record) tab model. Should only be called when both -// the current OTR tab model and the new OTR tab model are either nil or contain -// no tabs. This must be called after the otr tab model has been deleted because -// the incognito browser state is deleted. - (void)setOtrTabModel:(TabModel*)otrModel { - // No-op + self.mediator.incognitoTabModel = otrModel; } @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h index 5939870..fbd3dcf2 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h
@@ -10,11 +10,19 @@ #import "ios/chrome/browser/ui/main/main_coordinator.h" #import "ios/chrome/browser/ui/main/view_controller_swapping.h" +@protocol ApplicationCommands; @class TabModel; @protocol TabSwitcher; @interface TabGridCoordinator : MainCoordinator<ViewControllerSwapping> +- (instancetype)initWithWindow:(UIWindow*)window + applicationCommandEndpoint: + (id<ApplicationCommands>)applicationCommandEndpoint + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithWindow:(UIWindow*)window NS_UNAVAILABLE; + @property(nonatomic, readonly) id<TabSwitcher> tabSwitcher; @property(nonatomic, weak) TabModel* regularTabModel;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index 7ca45027..d5f61758 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -5,6 +5,9 @@ #import "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h" #import "ios/chrome/browser/tabs/tab_model.h" +#import "ios/chrome/browser/ui/commands/browser_commands.h" +#import "ios/chrome/browser/ui/commands/command_dispatcher.h" +#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/main/bvc_container_view_controller.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h" @@ -16,6 +19,9 @@ #endif @interface TabGridCoordinator () +// Commad dispatcher used while this coordinator's view controller is active. +// (for compatibility with the TabSwitcher protocol). +@property(nonatomic, strong) CommandDispatcher* dispatcher; // Object that internally backs the public TabSwitcher @property(nonatomic, strong) TabGridAdaptor* adaptor; // Container view controller for the BVC to live in; this class's view @@ -35,11 +41,25 @@ @synthesize regularTabModel = _regularTabModel; @synthesize incognitoTabModel = _incognitoTabModel; // Private properties. +@synthesize dispatcher = _dispatcher; @synthesize adaptor = _adaptor; @synthesize bvcContainer = _bvcContainer; @synthesize mediator = _mediator; @synthesize transitionHandler = _transitionHandler; +- (instancetype)initWithWindow:(nullable UIWindow*)window + applicationCommandEndpoint: + (id<ApplicationCommands>)applicationCommandEndpoint { + if ((self = [super initWithWindow:window])) { + _dispatcher = [[CommandDispatcher alloc] init]; + [_dispatcher startDispatchingToTarget:self + forProtocol:@protocol(BrowserCommands)]; + [_dispatcher startDispatchingToTarget:applicationCommandEndpoint + forProtocol:@protocol(ApplicationCommands)]; + } + return self; +} + #pragma mark - Public properties - (id<TabSwitcher>)tabSwitcher { @@ -64,12 +84,20 @@ self.window.rootViewController = self.mainViewController; self.adaptor = [[TabGridAdaptor alloc] init]; self.adaptor.tabGridViewController = self.mainViewController; + self.adaptor.adaptedDispatcher = + static_cast<id<ApplicationCommands, BrowserCommands, OmniboxFocuser, + ToolbarCommands>>(self.dispatcher); self.mediator = [[TabGridMediator alloc] init]; self.mediator.regularTabModel = self.regularTabModel; self.mediator.incognitoTabModel = self.incognitoTabModel; } +- (void)stop { + [self.dispatcher stopDispatchingForProtocol:@protocol(BrowserCommands)]; + [self.dispatcher stopDispatchingForProtocol:@protocol(ApplicationCommands)]; +} + #pragma mark - ViewControllerSwapping - (UIViewController*)activeViewController { @@ -126,9 +154,32 @@ self.bvcContainer.currentBVC = viewController; self.bvcContainer.transitioningDelegate = self.transitionHandler; BOOL animated = !self.animationsDisabledForTesting; + + // Extened |completion| to also signal the tab switcher delegate + // that the animated "tab switcher dismissal" (that is, presenting something + // on top of the tab switcher) transition has completed. + ProceduralBlock extendedCompletion = ^{ + [self.tabSwitcher.delegate + tabSwitcherDismissTransitionDidEnd:self.tabSwitcher]; + if (completion) { + completion(); + } + }; + [self.mainViewController presentViewController:self.bvcContainer animated:animated - completion:completion]; + completion:extendedCompletion]; +} + +#pragma mark - BrowserCommands + +- (void)openNewTab:(OpenNewTabCommand*)command { +} + +- (void)closeAllTabs { +} + +- (void)closeAllIncognitoTabs { } @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm index a122ed6f..78e39d6 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm
@@ -15,13 +15,34 @@ #error "This file requires ARC support." #endif +@interface TestTabSwitcherDelegate : NSObject<TabSwitcherDelegate> +@property(nonatomic) BOOL didEndCalled; +@end + +@implementation TestTabSwitcherDelegate +@synthesize didEndCalled = _didEndCalled; +- (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher + shouldFinishWithActiveModel:(TabModel*)tabModel { + // No-op. +} + +- (void)tabSwitcherDismissTransitionDidEnd:(id<TabSwitcher>)tabSwitcher { + self.didEndCalled = YES; +} + +- (id<ToolbarOwner>)tabSwitcherTransitionToolbarOwner { + return nil; +} +@end + namespace { -class TabGridViewCoordinatorTest : public BlockCleanupTest { +class TabGridCoordinatorTest : public BlockCleanupTest { public: - TabGridViewCoordinatorTest() { + TabGridCoordinatorTest() { UIWindow* window = [UIApplication sharedApplication].keyWindow; - coordinator_ = [[TabGridCoordinator alloc] initWithWindow:window]; + coordinator_ = [[TabGridCoordinator alloc] initWithWindow:window + applicationCommandEndpoint:nil]; coordinator_.animationsDisabledForTesting = YES; // TabGirdCoordinator will make its view controller the root, so stash the // original root view controller before starting |coordinator_|. @@ -30,6 +51,9 @@ [coordinator_ start]; + delegate_ = [[TestTabSwitcherDelegate alloc] init]; + coordinator_.tabSwitcher.delegate = delegate_; + normal_tab_view_controller_ = [[UIViewController alloc] init]; normal_tab_view_controller_.view.frame = CGRectMake(20, 20, 10, 10); @@ -37,7 +61,7 @@ incognito_tab_view_controller_.view.frame = CGRectMake(40, 40, 10, 10); } - ~TabGridViewCoordinatorTest() override {} + ~TabGridCoordinatorTest() override {} void TearDown() override { if (original_root_view_controller_) { @@ -52,6 +76,9 @@ // this VC as the root VC for the window. TabGridCoordinator* coordinator_; + // Delegate for the coordinator's TabSwitcher interface. + TestTabSwitcherDelegate* delegate_; + // The key window's original root view controller, which must be restored at // the end of the test. UIViewController* original_root_view_controller_; @@ -64,13 +91,13 @@ // Tests that the tab grid view controller is the initial active view // controller. -TEST_F(TabGridViewCoordinatorTest, InitialActiveViewController) { +TEST_F(TabGridCoordinatorTest, InitialActiveViewController) { EXPECT_EQ(coordinator_.mainViewController, coordinator_.activeViewController); } // Tests that it is possible to set a TabViewController without first setting a // TabSwitcher. -TEST_F(TabGridViewCoordinatorTest, TabViewControllerBeforeTabSwitcher) { +TEST_F(TabGridCoordinatorTest, TabViewControllerBeforeTabSwitcher) { [coordinator_ showTabViewController:normal_tab_view_controller_ completion:nil]; EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); @@ -83,7 +110,7 @@ // Tests that it is possible to set a TabViewController after setting a // TabSwitcher. -TEST_F(TabGridViewCoordinatorTest, TabViewControllerAfterTabSwitcher) { +TEST_F(TabGridCoordinatorTest, TabViewControllerAfterTabSwitcher) { [coordinator_ showTabSwitcher:coordinator_.tabSwitcher completion:nil]; EXPECT_EQ([coordinator_.tabSwitcher viewController], coordinator_.activeViewController); @@ -99,7 +126,7 @@ } // Tests swapping between two TabViewControllers. -TEST_F(TabGridViewCoordinatorTest, SwapTabViewControllers) { +TEST_F(TabGridCoordinatorTest, SwapTabViewControllers) { [coordinator_ showTabViewController:normal_tab_view_controller_ completion:nil]; EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); @@ -110,7 +137,7 @@ } // Tests calling showTabSwitcher twice in a row with the same VC. -TEST_F(TabGridViewCoordinatorTest, ShowTabSwitcherTwice) { +TEST_F(TabGridCoordinatorTest, ShowTabSwitcherTwice) { [coordinator_ showTabSwitcher:coordinator_.tabSwitcher completion:nil]; EXPECT_EQ([coordinator_.tabSwitcher viewController], coordinator_.activeViewController); @@ -121,7 +148,7 @@ } // Tests calling showTabViewController twice in a row with the same VC. -TEST_F(TabGridViewCoordinatorTest, ShowTabViewControllerTwice) { +TEST_F(TabGridCoordinatorTest, ShowTabViewControllerTwice) { [coordinator_ showTabViewController:normal_tab_view_controller_ completion:nil]; EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); @@ -133,7 +160,7 @@ // Tests that setting the active view controller work and that completion // handlers are called properly after the new view controller is made active. -TEST_F(TabGridViewCoordinatorTest, CompletionHandlers) { +TEST_F(TabGridCoordinatorTest, CompletionHandlers) { // Tests that the completion handler is called when showing the switcher. __block BOOL completion_handler_was_called = false; [coordinator_ showTabSwitcher:coordinator_.tabSwitcher @@ -146,7 +173,8 @@ ASSERT_TRUE(completion_handler_was_called); // Tests that the completion handler is called when showing a tab view - // controller. + // controller. Tests that the delegate 'didEnd' method is also called. + delegate_.didEndCalled = NO; completion_handler_was_called = NO; [coordinator_ showTabViewController:normal_tab_view_controller_ completion:^{ @@ -156,9 +184,11 @@ return completion_handler_was_called; }); ASSERT_TRUE(completion_handler_was_called); + EXPECT_TRUE(delegate_.didEndCalled); // Tests that the completion handler is called when replacing an existing tab - // view controller. + // view controller. Tests that the delegate 'didEnd' method is *not* called. + delegate_.didEndCalled = NO; completion_handler_was_called = NO; [coordinator_ showTabViewController:incognito_tab_view_controller_ completion:^{ @@ -168,10 +198,11 @@ return completion_handler_was_called; }); ASSERT_TRUE(completion_handler_was_called); + EXPECT_FALSE(delegate_.didEndCalled); } // Test that the tab grid coordinator sizes its view controller to the window. -TEST_F(TabGridViewCoordinatorTest, SizeTabGridCoordinatorViewController) { +TEST_F(TabGridCoordinatorTest, SizeTabGridCoordinatorViewController) { CGRect rect = [UIScreen mainScreen].bounds; [coordinator_ start]; EXPECT_TRUE(
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher.h b/ios/chrome/browser/ui/tab_switcher/tab_switcher.h index 6baac7c..282bab0 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_switcher.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
@@ -91,7 +91,7 @@ // perform an animation from the selected tab in the tab switcher to the // newly created tab in the content area. Objects adopting this protocol should // call the following delegate methods: -// |-tabSwitcher:dismissTransitionWillStartWithActiveModel:| +// |-tabSwitcher:shouldFinishWithActiveModel:| // |-tabSwitcherDismissTransitionDidEnd:| // to inform the delegate when this animation begins and ends. - (Tab*)dismissWithNewTabAnimationToModel:(TabModel*)targetModel
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h index 6c31c004..f620fca 100644 --- a/ios/net/cookies/cookie_store_ios.h +++ b/ios/net/cookies/cookie_store_ios.h
@@ -84,9 +84,6 @@ bool secure_source, bool modify_http_only, SetCookiesCallback callback) override; - void GetCookiesWithOptionsAsync(const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) override; void GetCookieListWithOptionsAsync(const GURL& url, const net::CookieOptions& options, GetCookieListCallback callback) override;
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm index d159c67..71b1ef0c 100644 --- a/ios/net/cookies/cookie_store_ios.mm +++ b/ios/net/cookies/cookie_store_ios.mm
@@ -150,20 +150,6 @@ return corrected_cookie; } - -// Builds a cookie line (such as "key1=value1; key2=value2") from an array of -// cookies. -std::string BuildCookieLineWithOptions(NSArray* cookies, - const net::CookieOptions& options) { - // The exclude_httponly() option would only be used by a javascript engine. - DCHECK(!options.exclude_httponly()); - - // This utility function returns all the cookies, including the httponly ones. - // This is fine because we don't support the exclude_httponly option. - NSDictionary* header = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies]; - return base::SysNSStringToUTF8([header valueForKey:@"Cookie"]); -} - // Returns an empty closure if |callback| is null callback or binds the // callback to |success|. base::OnceClosure BindSetCookiesCallback( @@ -176,16 +162,6 @@ return set_callback; } -// Runs |callback| on CookieLine generated from |options| and |cookies|. -void RunGetCookiesCallbackOnSystemCookies( - const net::CookieOptions& options, - CookieStoreIOS::GetCookiesCallback callback, - NSArray<NSHTTPCookie*>* cookies) { - if (!callback.is_null()) { - std::move(callback).Run(BuildCookieLineWithOptions(cookies, options)); - } -} - // Tests whether the |cookie| is a session cookie. bool IsCookieSessionCookie(NSHTTPCookie* cookie, base::Time time) { return [cookie isSessionOnly]; @@ -354,27 +330,6 @@ std::move(callback).Run(false); } -void CookieStoreIOS::GetCookiesWithOptionsAsync( - const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // If cookies are not allowed, a CookieStoreIOS subclass should be used - // instead. - DCHECK(SystemCookiesAllowed()); - - // The exclude_httponly() option would only be used by a javascript - // engine. - DCHECK(!options.exclude_httponly()); - - // TODO(crbug.com/459154): If/when iOS supports Same-Site cookies, we'll need - // to pass options in here as well. - system_store_->GetCookiesForURLAsync( - url, base::BindOnce(&RunGetCookiesCallbackOnSystemCookies, options, - base::Passed(&callback))); -} - void CookieStoreIOS::GetCookieListWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/ios/net/cookies/cookie_store_ios_persistent.h b/ios/net/cookies/cookie_store_ios_persistent.h index c20372c..09e96ce 100644 --- a/ios/net/cookies/cookie_store_ios_persistent.h +++ b/ios/net/cookies/cookie_store_ios_persistent.h
@@ -46,9 +46,6 @@ bool secure_source, bool modify_http_only, SetCookiesCallback callback) override; - void GetCookiesWithOptionsAsync(const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) override; void GetCookieListWithOptionsAsync(const GURL& url, const net::CookieOptions& options, GetCookieListCallback callback) override;
diff --git a/ios/net/cookies/cookie_store_ios_persistent.mm b/ios/net/cookies/cookie_store_ios_persistent.mm index ba3d109..3ab7a7c 100644 --- a/ios/net/cookies/cookie_store_ios_persistent.mm +++ b/ios/net/cookies/cookie_store_ios_persistent.mm
@@ -60,15 +60,6 @@ WrapSetCallback(std::move(callback))); } -void CookieStoreIOSPersistent::GetCookiesWithOptionsAsync( - const GURL& url, - const net::CookieOptions& options, - GetCookiesCallback callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - cookie_monster()->GetCookiesWithOptionsAsync(url, options, - std::move(callback)); -} - void CookieStoreIOSPersistent::GetCookieListWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/ios/net/cookies/cookie_store_ios_persistent_unittest.mm b/ios/net/cookies/cookie_store_ios_persistent_unittest.mm index a75b7161..d18ab9ee 100644 --- a/ios/net/cookies/cookie_store_ios_persistent_unittest.mm +++ b/ios/net/cookies/cookie_store_ios_persistent_unittest.mm
@@ -13,7 +13,9 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #import "ios/net/cookies/cookie_store_ios_test_util.h" +#include "net/cookies/canonical_cookie_test_helpers.h" #include "net/cookies/cookie_store_change_unittest.h" +#include "net/cookies/cookie_store_test_callbacks.h" #include "net/cookies/cookie_store_unittest.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -79,11 +81,11 @@ ~CookieStoreIOSPersistentTest() override {} // Gets the cookies. |callback| will be called on completion. - void GetCookies(net::CookieStore::GetCookiesCallback callback) { + void GetCookies(net::CookieStore::GetCookieListCallback callback) { net::CookieOptions options; options.set_include_httponly(); - store_->GetCookiesWithOptionsAsync(kTestCookieURL, options, - std::move(callback)); + store_->GetCookieListWithOptionsAsync(kTestCookieURL, options, + std::move(callback)); } // Sets a cookie. @@ -136,13 +138,12 @@ // Tests that cookies can be read before the backend is loaded. TEST_F(CookieStoreIOSPersistentTest, NotSynchronized) { // Start fetching the cookie. - GetCookieCallback callback; + GetCookieListCallback callback; GetCookies( - base::BindOnce(&GetCookieCallback::Run, base::Unretained(&callback))); + base::BindOnce(&GetCookieListCallback::Run, base::Unretained(&callback))); // Backend loading completes. backend_->RunLoadedCallback(); - EXPECT_TRUE(callback.did_run()); - EXPECT_EQ("a=b", callback.cookie_line()); + EXPECT_THAT(callback.cookies(), MatchesCookieLine("a=b")); } } // namespace net
diff --git a/ios/net/cookies/cookie_store_ios_test_util.h b/ios/net/cookies/cookie_store_ios_test_util.h index f70659cb..9a7a1ff 100644 --- a/ios/net/cookies/cookie_store_ios_test_util.h +++ b/ios/net/cookies/cookie_store_ios_test_util.h
@@ -11,6 +11,7 @@ #include "base/callback_forward.h" #include "base/task_scheduler/post_task.h" #include "ios/net/cookies/cookie_store_ios_client.h" +#include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store.h" #include "url/gurl.h" @@ -50,24 +51,6 @@ bool flushed_; }; -// Helper callback to be passed to CookieStore::GetCookiesWithOptionsAsync(). -class GetCookieCallback { - public: - GetCookieCallback(); - - // Returns true if the callback has been run. - bool did_run(); - - // Returns the parameter of the callback. - const std::string& cookie_line(); - - void Run(const std::string& cookie_line); - - private: - bool did_run_; - std::string cookie_line_; -}; - class TestCookieStoreIOSClient : public CookieStoreIOSClient { public: TestCookieStoreIOSClient();
diff --git a/ios/net/cookies/cookie_store_ios_test_util.mm b/ios/net/cookies/cookie_store_ios_test_util.mm index dc43803..091d589 100644 --- a/ios/net/cookies/cookie_store_ios_test_util.mm +++ b/ios/net/cookies/cookie_store_ios_test_util.mm
@@ -95,28 +95,6 @@ } #pragma mark - -#pragma mark GetCookieCallback - -GetCookieCallback::GetCookieCallback() : did_run_(false) {} - -#pragma mark - -#pragma mark GetCookieCallback methods - -bool GetCookieCallback::did_run() { - return did_run_; -} - -const std::string& GetCookieCallback::cookie_line() { - return cookie_line_; -} - -void GetCookieCallback::Run(const std::string& cookie_line) { - ASSERT_FALSE(did_run_); - did_run_ = true; - cookie_line_ = cookie_line; -} - -#pragma mark - #pragma mark TestCookieStoreIOSClient TestCookieStoreIOSClient::TestCookieStoreIOSClient() {}
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm index b8f0bab..3461b4e 100644 --- a/ios/net/cookies/cookie_store_ios_unittest.mm +++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -98,8 +98,7 @@ void IgnoreBoolean(bool ignored) { } -void IgnoreString(const std::string& ignored) { -} +void IgnoreList(const net::CookieList& ignored) {} } // namespace @@ -130,11 +129,11 @@ ~CookieStoreIOSTest() override {} // Gets the cookies. |callback| will be called on completion. - void GetCookies(net::CookieStore::GetCookiesCallback callback) { + void GetCookies(net::CookieStore::GetCookieListCallback callback) { net::CookieOptions options; options.set_include_httponly(); - store_->GetCookiesWithOptionsAsync(kTestCookieURLFooBar, options, - std::move(callback)); + store_->GetCookieListWithOptionsAsync(kTestCookieURLFooBar, options, + std::move(callback)); } // Sets a cookie. @@ -196,7 +195,7 @@ }; TEST_F(CookieStoreIOSTest, SetCookieCallsHookWhenSynchronized) { - GetCookies(base::Bind(&IgnoreString)); + GetCookies(base::BindOnce(&IgnoreList)); ClearCookies(); SetCookie("abc=def"); EXPECT_EQ(1U, cookies_changed_.size()); @@ -218,7 +217,7 @@ } TEST_F(CookieStoreIOSTest, DeleteCallsHook) { - GetCookies(base::Bind(&IgnoreString)); + GetCookies(base::BindOnce(&IgnoreList)); ClearCookies(); SetCookie("abc=def"); EXPECT_EQ(1U, cookies_changed_.size()); @@ -230,8 +229,7 @@ } TEST_F(CookieStoreIOSTest, SameValueDoesNotCallHook) { - GetCookieCallback callback; - GetCookies(base::Bind(&IgnoreString)); + GetCookies(base::BindOnce(&IgnoreList)); ClearCookies(); SetCookie("abc=def"); EXPECT_EQ(1U, cookies_changed_.size());
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn index 88424f6..9e629b4 100644 --- a/ios/web/web_state/ui/BUILD.gn +++ b/ios/web/web_state/ui/BUILD.gn
@@ -91,6 +91,8 @@ "//base", "//ios/web/public", "//ios/web/web_state:context_menu", + "//ios/web/web_state/ui:crw_wk_script_message_router", + "//ios/web/web_state/ui:wk_web_view_configuration_provider", ] sources = [
diff --git a/ios/web/web_state/ui/crw_context_menu_controller.h b/ios/web/web_state/ui/crw_context_menu_controller.h index a3242e9..dbf5c8d 100644 --- a/ios/web/web_state/ui/crw_context_menu_controller.h +++ b/ios/web/web_state/ui/crw_context_menu_controller.h
@@ -10,6 +10,10 @@ #import "ios/web/public/block_types.h" +namespace web { +class BrowserState; +} // namespace web + @protocol CRWContextMenuDelegate; @protocol CRWJSInjectionEvaluator; @@ -30,6 +34,7 @@ // event on |webView| and can have performance impact. // TODO(crbug.com/228179): This class only triggers context menu on mainFrame. - (instancetype)initWithWebView:(WKWebView*)webView + browserState:(web::BrowserState*)browserState injectionEvaluator:(id<CRWJSInjectionEvaluator>)injectionEvaluator delegate:(id<CRWContextMenuDelegate>)delegate NS_DESIGNATED_INITIALIZER;
diff --git a/ios/web/web_state/ui/crw_context_menu_controller.mm b/ios/web/web_state/ui/crw_context_menu_controller.mm index 95ac5c9..2dbe4c0 100644 --- a/ios/web/web_state/ui/crw_context_menu_controller.mm +++ b/ios/web/web_state/ui/crw_context_menu_controller.mm
@@ -7,16 +7,22 @@ #import <objc/runtime.h> #include <stddef.h> +#include "base/feature_list.h" #include "base/ios/ios_util.h" #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/sys_string_conversions.h" +#include "base/unguessable_token.h" +#include "ios/web/public/features.h" #import "ios/web/public/web_state/context_menu_params.h" #import "ios/web/public/web_state/js/crw_js_injection_evaluator.h" #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h" #import "ios/web/web_state/context_menu_constants.h" #import "ios/web/web_state/context_menu_params_utils.h" +#import "ios/web/web_state/ui/crw_wk_script_message_router.h" +#import "ios/web/web_state/ui/html_element_fetch_request.h" +#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -40,6 +46,11 @@ gesture_recognizer.enabled = YES; } } + +// JavaScript message handler name installed in WKWebView for found element +// response. +NSString* const kFindElementResultHandlerName = @"FindElementResultHandler"; + } // namespace @interface CRWContextMenuController ()<UIGestureRecognizerDelegate> @@ -75,9 +86,14 @@ completionHandler:(void (^)(NSDictionary*))handler; // Sets the value of |_DOMElementForLastTouch|. - (void)setDOMElementForLastTouch:(NSDictionary*)element; +// Called to process a message received from JavaScript. +- (void)didReceiveScriptMessage:(WKScriptMessage*)message; // Logs the time taken to fetch DOM element details. - (void)logElementFetchDurationWithStartTime: (base::TimeTicks)elementFetchStartTime; +// Cancels the display of the context menu and clears associated element fetch +// request state. +- (void)cancelContextMenuDisplay; // Forwards the execution of |script| to |javaScriptDelegate| and if it is nil, // to |webView|. - (void)executeJavaScript:(NSString*)script @@ -103,6 +119,10 @@ BOOL _contextMenuNeedsDisplay; // The location of the last reconized long press in the |webView|. CGPoint _locationForLastTouch; + // Details for currently in progress element fetches. The objects are + // instances of HTMLElementFetchRequest and are keyed by a unique requestID + // string. + NSMutableDictionary* _pendingElementFetchRequests; } @synthesize delegate = _delegate; @@ -110,6 +130,7 @@ @synthesize webView = _webView; - (instancetype)initWithWebView:(WKWebView*)webView + browserState:(web::BrowserState*)browserState injectionEvaluator:(id<CRWJSInjectionEvaluator>)injectionEvaluator delegate:(id<CRWContextMenuDelegate>)delegate { DCHECK(webView); @@ -118,6 +139,7 @@ _webView = webView; _delegate = delegate; _injectionEvaluator = injectionEvaluator; + _pendingElementFetchRequests = [[NSMutableDictionary alloc] init]; // The system context menu triggers after 0.55 second. Add a gesture // recognizer with a shorter delay to be able to cancel the system menu if @@ -154,6 +176,21 @@ OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } + + if (base::FeatureList::IsEnabled( + web::features::kContextMenuElementPostMessage)) { + // Listen for fetched element response. + web::WKWebViewConfigurationProvider& configurationProvider = + web::WKWebViewConfigurationProvider::FromBrowserState(browserState); + CRWWKScriptMessageRouter* messageRouter = + configurationProvider.GetScriptMessageRouter(); + __weak CRWContextMenuController* weakSelf = self; + [messageRouter setScriptMessageHandler:^(WKScriptMessage* message) { + [weakSelf didReceiveScriptMessage:message]; + } + name:kFindElementResultHandlerName + webView:webView]; + } } return self; } @@ -203,7 +240,7 @@ [self longPressGestureRecognizerBegan]; break; case UIGestureRecognizerStateEnded: - _contextMenuNeedsDisplay = NO; + [self cancelContextMenuDisplay]; break; case UIGestureRecognizerStateChanged: [self longPressGestureRecognizerChanged]; @@ -251,7 +288,7 @@ float deltaY = std::abs(_locationForLastTouch.y - currentTouchLocation.y); if (deltaX > kLongPressMoveDeltaPixels || deltaY > kLongPressMoveDeltaPixels) { - _contextMenuNeedsDisplay = NO; + [self cancelContextMenuDisplay]; } } @@ -289,12 +326,32 @@ } } +- (void)didReceiveScriptMessage:(WKScriptMessage*)message { + NSDictionary* response = message.body; + NSString* requestID = response[web::kContextMenuElementRequestID]; + HTMLElementFetchRequest* fetchRequest = + _pendingElementFetchRequests[requestID]; + // Do not process the message if a fetch request with a matching |requestID| + // was not found. This ensures that the response matches a request made by + // this CRWContextMenuController instance. + if (fetchRequest) { + [_pendingElementFetchRequests removeObjectForKey:requestID]; + [self logElementFetchDurationWithStartTime:fetchRequest.creationTime]; + [fetchRequest runHandlerWithResponse:response]; + } +} + - (void)logElementFetchDurationWithStartTime: (base::TimeTicks)elementFetchStartTime { UMA_HISTOGRAM_TIMES("ContextMenu.DOMElementFetchDuration", base::TimeTicks::Now() - elementFetchStartTime); } +- (void)cancelContextMenuDisplay { + _contextMenuNeedsDisplay = NO; + [_pendingElementFetchRequests removeAllObjects]; +} + #pragma mark - #pragma mark UIGestureRecognizerDelegate @@ -317,7 +374,7 @@ // menu and show another one. If for some reason context menu info is not // fetched - system context menu will be shown. [self setDOMElementForLastTouch:nil]; - _contextMenuNeedsDisplay = NO; + [self cancelContextMenuDisplay]; base::TimeTicks fetchStartTime = base::TimeTicks::Now(); __weak CRWContextMenuController* weakSelf = self; @@ -350,18 +407,47 @@ - (void)fetchDOMElementAtPoint:(CGPoint)point completionHandler:(void (^)(NSDictionary*))handler { DCHECK(handler); + CGPoint scrollOffset = self.scrollPosition; CGSize webViewContentSize = self.webScrollView.contentSize; CGFloat webViewContentWidth = webViewContentSize.width; CGFloat webViewContentHeight = webViewContentSize.height; - NSString* getElementScript = [NSString - stringWithFormat:@"__gCrWeb.getElementFromPoint(%g, %g, %g, %g);", - point.x + scrollOffset.x, point.y + scrollOffset.y, - webViewContentWidth, webViewContentHeight]; - [self executeJavaScript:getElementScript - completionHandler:^(id element, NSError*) { - handler(base::mac::ObjCCastStrict<NSDictionary>(element)); - }]; + + NSString* formatString; + web::JavaScriptResultBlock completionHandler = nil; + if (base::FeatureList::IsEnabled( + web::features::kContextMenuElementPostMessage)) { + NSString* requestID = + base::SysUTF8ToNSString(base::UnguessableToken::Create().ToString()); + HTMLElementFetchRequest* fetchRequest = + [[HTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; + _pendingElementFetchRequests[requestID] = fetchRequest; + + formatString = + [NSString stringWithFormat: + @"__gCrWeb.findElementAtPoint('%@', %%g, %%g, %%g, %%g);", + requestID]; + } else { + formatString = @"__gCrWeb.getElementFromPoint(%g, %g, %g, %g);"; + base::TimeTicks getElementStartTime = base::TimeTicks::Now(); + __weak CRWContextMenuController* weakSelf = self; + completionHandler = ^(id element, NSError* error) { + [weakSelf logElementFetchDurationWithStartTime:getElementStartTime]; + if (error.code == WKErrorWebContentProcessTerminated || + error.code == WKErrorWebViewInvalidated) { + // Renderer was terminated or view deallocated. + handler(nil); + } else { + handler(base::mac::ObjCCastStrict<NSDictionary>(element)); + } + }; + } + + NSString* getElementScript = + [NSString stringWithFormat:formatString, point.x + scrollOffset.x, + point.y + scrollOffset.y, webViewContentWidth, + webViewContentHeight]; + [self executeJavaScript:getElementScript completionHandler:completionHandler]; } @end
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 2537d9b..693e405 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3846,8 +3846,10 @@ requireGestureRecognizerToFail:swipeRecognizer]; } + web::BrowserState* browserState = self.webStateImpl->GetBrowserState(); _contextMenuController = [[CRWContextMenuController alloc] initWithWebView:_webView + browserState:browserState injectionEvaluator:self delegate:self];
diff --git a/ios/web/web_state/web_view_internal_creation_util.mm b/ios/web/web_state/web_view_internal_creation_util.mm index 595b141..69facc5 100644 --- a/ios/web/web_state/web_view_internal_creation_util.mm +++ b/ios/web/web_state/web_view_internal_creation_util.mm
@@ -60,6 +60,7 @@ if (context_menu_delegate) { CRWContextMenuController* context_menu_controller = [ [CRWContextMenuController alloc] initWithWebView:web_view + browserState:browser_state injectionEvaluator:nil delegate:context_menu_delegate]; void* associated_object_key = (__bridge void*)context_menu_controller;
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index d12c553..1dabafb 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -263,6 +263,7 @@ "internal/cwv_html_element_unittest.mm", "internal/cwv_preferences_unittest.mm", "internal/cwv_preview_element_info_unittest.mm", + "internal/translate/cwv_translation_controller_unittest.mm", "internal/translate/cwv_translation_language_unittest.mm", "internal/translate/cwv_translation_policy_unittest.mm", "internal/web_view_web_client_unittest.mm",
diff --git a/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm b/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm new file mode 100644 index 0000000..8430c989 --- /dev/null +++ b/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm
@@ -0,0 +1,123 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web_view/internal/translate/cwv_translation_controller_internal.h" + +#import <Foundation/Foundation.h> + +#include <memory> + +#include "base/strings/sys_string_conversions.h" +#import "ios/web/public/test/fakes/crw_test_js_injection_receiver.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_view/internal/translate/cwv_translation_language_internal.h" +#import "ios/web_view/internal/translate/web_view_translate_client.h" +#include "ios/web_view/internal/web_view_browser_state.h" +#import "ios/web_view/public/cwv_translation_controller_delegate.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace ios_web_view { + +namespace { +NSString* const kTestFromLangCode = @"ja"; +NSString* const kTestToLangCode = @"en"; +} // namespace + +class CWVTranslationControllerTest : public PlatformTest { + protected: + CWVTranslationControllerTest() : browser_state_(/*off_the_record=*/false) { + web_state_.SetBrowserState(&browser_state_); + auto test_navigation_manager = + std::make_unique<web::TestNavigationManager>(); + web_state_.SetNavigationManager(std::move(test_navigation_manager)); + CRWTestJSInjectionReceiver* injection_receiver = + [[CRWTestJSInjectionReceiver alloc] init]; + web_state_.SetJSInjectionReceiver(injection_receiver); + WebViewTranslateClient::CreateForWebState(&web_state_); + translate_client_ = WebViewTranslateClient::FromWebState(&web_state_); + translation_controller_ = [[CWVTranslationController alloc] + initWithTranslateClient:translate_client_]; + } + + // Checks if |lang_code| matches the OCMArg's CWVTranslationLanguage. + id CheckLanguageCode(NSString* lang_code) WARN_UNUSED_RESULT { + return [OCMArg checkWithBlock:^BOOL(CWVTranslationLanguage* lang) { + return [lang.languageCode isEqualToString:lang_code]; + }]; + } + + web::TestWebThreadBundle web_thread_bundle_; + WebViewBrowserState browser_state_; + web::TestWebState web_state_; + WebViewTranslateClient* translate_client_; + CWVTranslationController* translation_controller_; +}; + +// Tests CWVTranslationController invokes can offer delegate method. +TEST_F(CWVTranslationControllerTest, CanOfferCallback) { + id delegate = OCMProtocolMock(@protocol(CWVTranslationControllerDelegate)); + translation_controller_.delegate = delegate; + + [[delegate expect] translationController:translation_controller_ + canOfferTranslationFromLanguage:CheckLanguageCode(kTestFromLangCode) + toLanguage:CheckLanguageCode(kTestToLangCode)]; + translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_BEFORE_TRANSLATE, + base::SysNSStringToUTF8(kTestFromLangCode), + base::SysNSStringToUTF8(kTestToLangCode), + translate::TranslateErrors::NONE, + /*triggered_from_menu=*/false); + + [delegate verify]; +} + +// Tests CWVTranslationController invokes did start delegate method. +TEST_F(CWVTranslationControllerTest, DidStartCallback) { + id delegate = OCMProtocolMock(@protocol(CWVTranslationControllerDelegate)); + translation_controller_.delegate = delegate; + + [[delegate expect] translationController:translation_controller_ + didStartTranslationFromLanguage:CheckLanguageCode(kTestFromLangCode) + toLanguage:CheckLanguageCode(kTestToLangCode) + userInitiated:YES]; + translate_client_->ShowTranslateUI(translate::TRANSLATE_STEP_TRANSLATING, + base::SysNSStringToUTF8(kTestFromLangCode), + base::SysNSStringToUTF8(kTestToLangCode), + translate::TranslateErrors::NONE, + /*triggered_from_menu=*/true); + + [delegate verify]; +} + +// Tests CWVTranslationController invokes did finish delegate method. +TEST_F(CWVTranslationControllerTest, DidFinishCallback) { + id delegate = OCMProtocolMock(@protocol(CWVTranslationControllerDelegate)); + translation_controller_.delegate = delegate; + + id check_error_code = [OCMArg checkWithBlock:^BOOL(NSError* error) { + return error.code == CWVTranslationErrorInitializationError; + }]; + [[delegate expect] translationController:translation_controller_ + didFinishTranslationFromLanguage:CheckLanguageCode(kTestFromLangCode) + toLanguage:CheckLanguageCode(kTestToLangCode) + error:check_error_code]; + translate_client_->ShowTranslateUI( + translate::TRANSLATE_STEP_AFTER_TRANSLATE, + base::SysNSStringToUTF8(kTestFromLangCode), + base::SysNSStringToUTF8(kTestToLangCode), + translate::TranslateErrors::INITIALIZATION_ERROR, + /*triggered_from_menu=*/false); + + [delegate verify]; +} + +} // namespace ios_web_view
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn index 7985db2..b4fe7ed 100644 --- a/media/cast/BUILD.gn +++ b/media/cast/BUILD.gn
@@ -265,7 +265,6 @@ "//net", "//testing/gtest", "//third_party/libyuv", - "//third_party/mt19937ar", "//ui/gfx:test_support", ]
diff --git a/media/cast/DEPS b/media/cast/DEPS index e44afe0..d1cb7e6 100644 --- a/media/cast/DEPS +++ b/media/cast/DEPS
@@ -1,9 +1,8 @@ include_rules = [ - "+crypto", - "+media", - "+net", + "+crypto", + "+media", + "+net", "+third_party/libyuv", - "+third_party/mt19937ar", "+third_party/zlib", "+ui/gfx", ]
diff --git a/media/cast/test/utility/udp_proxy.cc b/media/cast/test/utility/udp_proxy.cc index 1cd8fbd..1a3f64f 100644 --- a/media/cast/test/utility/udp_proxy.cc +++ b/media/cast/test/utility/udp_proxy.cc
@@ -422,8 +422,8 @@ coef_variance_(coef_variance), rate_index_(0), on_state_(true), + mt_rand_(rand_seed), weak_factory_(this) { - mt_rand_.init_genrand(rand_seed); DCHECK(!average_rates.empty()); ComputeRates(); } @@ -461,9 +461,9 @@ double InterruptedPoissonProcess::RandDouble() { // Generate a 64-bits random number from MT19937 and then convert // it to double. - uint64_t rand = mt_rand_.genrand_int32(); + uint64_t rand = mt_rand_(); rand <<= 32; - rand |= mt_rand_.genrand_int32(); + rand |= mt_rand_(); return base::BitsToOpenEndedUnitInterval(rand); }
diff --git a/media/cast/test/utility/udp_proxy.h b/media/cast/test/utility/udp_proxy.h index 046a214..dc581084 100644 --- a/media/cast/test/utility/udp_proxy.h +++ b/media/cast/test/utility/udp_proxy.h
@@ -9,6 +9,7 @@ #include <stdint.h> #include <memory> +#include <random> #include <vector> #include "base/macros.h" @@ -18,7 +19,6 @@ #include "base/single_thread_task_runner.h" #include "media/cast/net/cast_transport_config.h" #include "net/base/ip_endpoint.h" -#include "third_party/mt19937ar/mt19937ar.h" namespace net { class NetLog; @@ -99,7 +99,7 @@ std::vector<base::WeakPtr<InternalBuffer> > send_buffers_; // Fast pseudo random number generator. - MersenneTwister mt_rand_; + std::mt19937 mt_rand_; base::WeakPtrFactory<InterruptedPoissonProcess> weak_factory_;
diff --git a/media/filters/video_renderer_algorithm.cc b/media/filters/video_renderer_algorithm.cc index 381a904..aa98ee6c 100644 --- a/media/filters/video_renderer_algorithm.cc +++ b/media/filters/video_renderer_algorithm.cc
@@ -79,23 +79,20 @@ ++ready_frame.render_count; UpdateEffectiveFramesQueued(); - // If time stops, we should reset the |first_frame_| marker, since we can no - // longer use cadence overage information for this frame. + // If time stops, we should reset the |first_frame_| marker. if (!was_time_moving_) first_frame_ = true; return ready_frame.frame; } last_deadline_max_ = deadline_max; - base::TimeDelta selected_frame_drift; + base::TimeDelta selected_frame_drift, cadence_frame_drift; // Step 4: Attempt to find the best frame by cadence. - int cadence_overage = 0; - const int cadence_frame = - FindBestFrameByCadence(first_frame_ ? nullptr : &cadence_overage); + const int cadence_frame = FindBestFrameByCadence(); int frame_to_render = cadence_frame; if (frame_to_render >= 0) { - selected_frame_drift = + cadence_frame_drift = selected_frame_drift = CalculateAbsoluteDriftForFrame(deadline_min, frame_to_render); } @@ -133,8 +130,12 @@ const bool ignored_cadence_frame = cadence_frame >= 0 && frame_to_render != cadence_frame; if (ignored_cadence_frame) { - cadence_overage = 0; - DVLOG(2) << "Cadence frame overridden by drift: " << selected_frame_drift; + DVLOG(2) << "Cadence frame " + << frame_queue_[cadence_frame].frame->timestamp() << " (" + << cadence_frame << ") overridden by drift: " + << cadence_frame_drift.InMillisecondsF() << "ms, using " + << frame_queue_[frame_to_render].frame->timestamp() << "(" + << frame_to_render << ") instead."; } last_render_had_glitch_ = selected_frame_drift > max_acceptable_drift_; @@ -205,30 +206,14 @@ } // Step 8: Congratulations, the frame selection gauntlet has been passed! - // - // If we ended up choosing a frame selected by cadence, carry over the overage - // values from the previous frame. Overage is treated as having been - // displayed and dropped for each count. If the frame wasn't selected by - // cadence, |cadence_overage| will be zero. - // - // Frames far into the future may be rendered many times before video playback - // starts, so we always ignore any overages for the first frame. - if (first_frame_ && frame_to_render > 0) { - DCHECK_EQ(cadence_overage, 0); + if (first_frame_ && frame_to_render > 0) first_frame_ = false; - } - // Ignore one frame of overage if the last call to Render() ignored the - // frame selected by cadence due to drift. - if (last_render_ignored_cadence_frame_ && cadence_overage > 0) - cadence_overage -= 1; + ++frame_queue_.front().render_count; - last_render_ignored_cadence_frame_ = ignored_cadence_frame; - frame_queue_.front().render_count += cadence_overage + 1; - frame_queue_.front().drop_count += cadence_overage; - - // Once we reach a glitch in our cadence sequence, reset the base frame - // number used for defining the cadence sequence. + // Once we reach a glitch in our cadence sequence, reset the base frame number + // used for defining the cadence sequence; the sequence restarts from the + // selected frame. if (ignored_cadence_frame) { cadence_frame_counter_ = 0; UpdateCadenceForFrames(); @@ -322,7 +307,6 @@ } first_frame_ = true; effective_frames_queued_ = cadence_frame_counter_ = 0; - last_render_ignored_cadence_frame_ = false; was_time_moving_ = false; // Default to ATSC IS/191 recommendations for maximum acceptable drift before @@ -589,8 +573,7 @@ } } -int VideoRendererAlgorithm::FindBestFrameByCadence( - int* remaining_overage) const { +int VideoRendererAlgorithm::FindBestFrameByCadence() const { DCHECK(!frame_queue_.empty()); if (!cadence_estimator_.has_cadence()) return -1; @@ -599,34 +582,15 @@ DCHECK(cadence_estimator_.has_cadence()); const ReadyFrame& current_frame = frame_queue_.front(); - if (remaining_overage) { - DCHECK_EQ(*remaining_overage, 0); - } - // If the current frame is below cadence, we should prefer it. if (current_frame.render_count < current_frame.ideal_render_count) return 0; - // For over-rendered frames we need to ensure we skip frames and subtract - // each skipped frame's ideal cadence from the over-render count until we - // find a frame which still has a positive ideal render count. - int render_count_overage = std::max( - 0, current_frame.render_count - current_frame.ideal_render_count); - // If the current frame is on cadence or over cadence, find the next frame // with a positive ideal render count. for (size_t i = 1; i < frame_queue_.size(); ++i) { - const ReadyFrame& frame = frame_queue_[i]; - if (frame.ideal_render_count > render_count_overage) { - if (remaining_overage) - *remaining_overage = render_count_overage; + if (frame_queue_[i].ideal_render_count > 0) return i; - } else { - // The ideal render count should always be zero or smaller than the - // over-render count. - render_count_overage -= frame.ideal_render_count; - DCHECK_GE(render_count_overage, 0); - } } // We don't have enough frames to find a better once by cadence. @@ -785,7 +749,7 @@ } // Find the first usable frame to start counting from. - const int start_index = FindBestFrameByCadence(nullptr); + const int start_index = FindBestFrameByCadence(); if (start_index < 0) return 0;
diff --git a/media/filters/video_renderer_algorithm.h b/media/filters/video_renderer_algorithm.h index 64bcf3a6..84a2260 100644 --- a/media/filters/video_renderer_algorithm.h +++ b/media/filters/video_renderer_algorithm.h
@@ -222,14 +222,7 @@ // If |cadence_estimator_| has detected a valid cadence, attempts to find the // next frame which should be rendered. Returns -1 if not enough frames are // available for cadence selection or there is no cadence. - // - // Returns the number of times a prior frame was over displayed and ate into - // the returned frames ideal render count via |remaining_overage|. - // - // For example, if we have 2 frames and each has an ideal display count of 3, - // but the first was displayed 4 times, the best frame is the second one, but - // it should only be displayed twice instead of thrice, so it's overage is 1. - int FindBestFrameByCadence(int* remaining_overage) const; + int FindBestFrameByCadence() const; // Iterates over |frame_queue_| and finds the frame which covers the most of // the deadline interval. If multiple frames have coverage of the interval, @@ -331,10 +324,6 @@ // ReadyFrameQueue. Cleared when a new cadence is detected. uint64_t cadence_frame_counter_; - // Tracks whether the last call to Render() choose to ignore the frame chosen - // by cadence in favor of one by drift or coverage. - bool last_render_ignored_cadence_frame_; - // Indicates if time was moving, set to the return value from // UpdateFrameStatistics() during Render() or externally by // set_time_stopped().
diff --git a/media/filters/video_renderer_algorithm_unittest.cc b/media/filters/video_renderer_algorithm_unittest.cc index c14f6ad..28bd807b 100644 --- a/media/filters/video_renderer_algorithm_unittest.cc +++ b/media/filters/video_renderer_algorithm_unittest.cc
@@ -584,7 +584,7 @@ ASSERT_EQ(1, GetCurrentFrameDropCount()); // Render the frame and check counts at each step. - const int kLastValue = 2 * 5 + 2; // Cadence is 2. + const int kLastValue = 2 * 5 + 2 - 1; // Cadence is 2, -1 for Render() above. for (int i = 0; i < kLastValue; ++i) { frame = RenderAndStep(&display_tg, &frames_dropped); ASSERT_TRUE(frame); @@ -924,8 +924,9 @@ algorithm_.EnqueueFrame(CreateFrame(frame_tg.interval(2))); algorithm_.EnqueueFrame(CreateFrame(frame_tg.interval(3))); - // The next frame should only be displayed once, since the previous one was - // over displayed by one frame. + // The next frame should still be displayed once, even though the previous + // one was displayed twice; the eventual drift reset will correct this (tested + // by BestFrameByCadenceOverdisplayedForDrift below). size_t frames_dropped = 0; scoped_refptr<VideoFrame> frame = RenderAndStep(&display_tg, &frames_dropped); ASSERT_TRUE(frame); @@ -935,14 +936,6 @@ // Enqueuing a new frame should keep the correct cadence values. algorithm_.EnqueueFrame(CreateFrame(frame_tg.interval(4))); - ASSERT_EQ(2, GetCurrentFrameDisplayCount()); - ASSERT_EQ(1, GetCurrentFrameDropCount()); - ASSERT_EQ(2, GetCurrentFrameIdealDisplayCount()); - - frame = RenderAndStep(&display_tg, &frames_dropped); - ASSERT_TRUE(frame); - EXPECT_EQ(frame_tg.interval(3), frame->timestamp()); - EXPECT_EQ(0u, frames_dropped); ASSERT_EQ(1, GetCurrentFrameDisplayCount()); ASSERT_EQ(0, GetCurrentFrameDropCount()); ASSERT_EQ(2, GetCurrentFrameIdealDisplayCount());
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc index fe3f67b..ff46050 100644 --- a/media/renderers/video_renderer_impl_unittest.cc +++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -410,15 +410,14 @@ WaitableMessageLoopEvent event; EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) .WillOnce(RunClosure(event.GetClosure())); - EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(20))).Times(1); + EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(60))).Times(1); EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); - AdvanceTimeInMs(20); + AdvanceTimeInMs(79); event.RunAndWait(); Mock::VerifyAndClearExpectations(&mock_cb_); } - AdvanceTimeInMs(59); - EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); + EXPECT_EQ(1u, renderer_->frames_queued_for_testing()); time_source_.StopTicking(); renderer_->OnTimeStopped(); EXPECT_EQ(0u, renderer_->frames_queued_for_testing());
diff --git a/net/BUILD.gn b/net/BUILD.gn index 2edaccf..61b0f45 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -2561,6 +2561,7 @@ "cert/mock_cert_verifier.h", "cert/mock_client_cert_verifier.cc", "cert/mock_client_cert_verifier.h", + "cookies/canonical_cookie_test_helpers.h", "cookies/cookie_monster_store_test.cc", "cookies/cookie_monster_store_test.h", "cookies/cookie_store_change_unittest.h", @@ -4785,7 +4786,6 @@ "cookies/canonical_cookie_unittest.cc", "cookies/cookie_constants_unittest.cc", "cookies/cookie_monster_unittest.cc", - "cookies/cookie_store_unittest.cc", "cookies/cookie_util_unittest.cc", "cookies/parsed_cookie_unittest.cc", "der/encode_values_unittest.cc",
diff --git a/net/cert/ev_root_ca_metadata.cc b/net/cert/ev_root_ca_metadata.cc index 8880c1c..b622b403 100644 --- a/net/cert/ev_root_ca_metadata.cc +++ b/net/cert/ev_root_ca_metadata.cc
@@ -261,6 +261,38 @@ 0x71, 0x4a, 0xea, 0xfb, 0x23, 0x49, 0xab, 0x39, 0x3d, 0xa3}}, {"1.3.6.1.4.1.6334.1.100.1", ""}, }, + // DigiCert Assured ID Root CA + // https://assured-id-root-ca.chain-demos.digicert.com/ + { + {{0x3e, 0x90, 0x99, 0xb5, 0x01, 0x5e, 0x8f, 0x48, 0x6c, 0x00, 0xbc, + 0xea, 0x9d, 0x11, 0x1e, 0xe7, 0x21, 0xfa, 0xba, 0x35, 0x5a, 0x89, + 0xbc, 0xf1, 0xdf, 0x69, 0x56, 0x1e, 0x3d, 0xc6, 0x32, 0x5c}}, + {"2.16.840.1.114412.2.1", ""}, + }, + // DigiCert Global Root CA + // https://global-root-ca.chain-demos.digicert.com/ + { + {{0x43, 0x48, 0xa0, 0xe9, 0x44, 0x4c, 0x78, 0xcb, 0x26, 0x5e, 0x05, + 0x8d, 0x5e, 0x89, 0x44, 0xb4, 0xd8, 0x4f, 0x96, 0x62, 0xbd, 0x26, + 0xdb, 0x25, 0x7f, 0x89, 0x34, 0xa4, 0x43, 0xc7, 0x01, 0x61}}, + {"2.16.840.1.114412.2.1", ""}, + }, + // DigiCert Global Root G2 + // https://global-root-g2.chain-demos.digicert.com/ + { + {{0xcb, 0x3c, 0xcb, 0xb7, 0x60, 0x31, 0xe5, 0xe0, 0x13, 0x8f, 0x8d, + 0xd3, 0x9a, 0x23, 0xf9, 0xde, 0x47, 0xff, 0xc3, 0x5e, 0x43, 0xc1, + 0x14, 0x4c, 0xea, 0x27, 0xd4, 0x6a, 0x5a, 0xb1, 0xcb, 0x5f}}, + {"2.16.840.1.114412.2.1", ""}, + }, + // DigiCert Global Root G3 + // https://global-root-g3.chain-demos.digicert.com/ + { + {{0x31, 0xad, 0x66, 0x48, 0xf8, 0x10, 0x41, 0x38, 0xc7, 0x38, 0xf3, + 0x9e, 0xa4, 0x32, 0x01, 0x33, 0x39, 0x3e, 0x3a, 0x18, 0xcc, 0x02, + 0x29, 0x6e, 0xf9, 0x7c, 0x2a, 0xc9, 0xef, 0x67, 0x31, 0xd0}}, + {"2.16.840.1.114412.2.1", ""}, + }, // DigiCert High Assurance EV Root CA // https://www.digicert.com { @@ -269,6 +301,14 @@ 0x0b, 0xa6, 0xab, 0xd7, 0x80, 0x6e, 0xd3, 0xb1, 0x18, 0xcf}}, {"2.16.840.1.114412.2.1", ""}, }, + // DigiCert Trusted Root G4 + // https://trusted-root-g4.chain-demos.digicert.com/ + { + {{0x55, 0x2f, 0x7b, 0xdc, 0xf1, 0xa7, 0xaf, 0x9e, 0x6c, 0xe6, 0x72, + 0x01, 0x7f, 0x4f, 0x12, 0xab, 0xf7, 0x72, 0x40, 0xc7, 0x8e, 0x76, + 0x1a, 0xc2, 0x03, 0xd1, 0xd9, 0xd2, 0x0a, 0xc8, 0x99, 0x88}}, + {"2.16.840.1.114412.2.1", ""}, + }, // D-TRUST Root Class 3 CA 2 EV 2009 // https://certdemo-ev-valid.ssl.d-trust.net/ {
diff --git a/net/cookies/canonical_cookie_test_helpers.h b/net/cookies/canonical_cookie_test_helpers.h new file mode 100644 index 0000000..bb730a57 --- /dev/null +++ b/net/cookies/canonical_cookie_test_helpers.h
@@ -0,0 +1,26 @@ +// 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 NET_COOKIES_CANONICAL_COOKIE_TEST_HELPERS_H_ +#define NET_COOKIES_CANONICAL_COOKIE_TEST_HELPERS_H_ + +#include <string> + +#include "net/cookies/canonical_cookie.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace net { + +MATCHER_P(MatchesCookieLine, cookie_line, "") { + std::string argument_line = CanonicalCookie::BuildCookieLine(arg); + if (argument_line == cookie_line) + return true; + + *result_listener << argument_line; + return false; +} + +} // namespace net + +#endif // NET_COOKIES_CANONICAL_COOKIE_TEST_HELPERS_H_ \ No newline at end of file
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 85aa1e7b..082e4b8b 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -210,8 +210,6 @@ const int kVlogPerCookieMonster = 1; const int kVlogGarbageCollection = 5; const int kVlogSetCookies = 7; -const int kVlogGetCookies = 9; - // Mozilla sorts on the path length (longest first), and then it // sorts by creation time (oldest first). // The RFC says the sort order for the domain attribute is undefined. @@ -491,19 +489,6 @@ url); } -void CookieMonster::GetCookiesWithOptionsAsync(const GURL& url, - const CookieOptions& options, - GetCookiesCallback callback) { - DoCookieCallbackForURL( - base::BindOnce( - // base::Unretained is safe as DoCookieCallbackForURL stores - // the callback on |*this|, so the callback will not outlive - // the object. - &CookieMonster::GetCookiesWithOptions, base::Unretained(this), url, - options, std::move(callback)), - url); -} - void CookieMonster::GetCookieListWithOptionsAsync( const GURL& url, const CookieOptions& options, @@ -788,24 +773,6 @@ std::move(callback)); } -void CookieMonster::GetCookiesWithOptions(const GURL& url, - const CookieOptions& options, - GetCookiesCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - std::string cookie_line; - if (HasCookieableScheme(url)) { - std::vector<CanonicalCookie*> cookies; - FindCookiesForHostAndDomain(url, options, &cookies); - std::sort(cookies.begin(), cookies.end(), CookieSorter); - - cookie_line = BuildCookieLine(cookies); - - VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line; - } - MaybeRunCookieCallback(std::move(callback), cookie_line); -} - void CookieMonster::DeleteCookie(const GURL& url, const std::string& cookie_name, base::OnceClosure callback) {
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index 6b36bc8..a77b1574 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h
@@ -161,9 +161,6 @@ bool secure_source, bool modify_http_only, SetCookiesCallback callback) override; - void GetCookiesWithOptionsAsync(const GURL& url, - const CookieOptions& options, - GetCookiesCallback callback) override; void GetCookieListWithOptionsAsync(const GURL& url, const CookieOptions& options, GetCookieListCallback callback) override; @@ -398,10 +395,6 @@ const CookieOptions& options, SetCookiesCallback callback); - void GetCookiesWithOptions(const GURL& url, - const CookieOptions& options, - GetCookiesCallback callback); - void DeleteCookie(const GURL& url, const std::string& cookie_name, base::OnceClosure callback);
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc index 05cfafd..b209476 100644 --- a/net/cookies/cookie_monster_perftest.cc +++ b/net/cookies/cookie_monster_perftest.cc
@@ -27,10 +27,6 @@ const char kCookieLine[] = "A = \"b=;\\\"\" ;secure;;;"; const char kGoogleURL[] = "http://www.foo.com"; -int CountInString(const std::string& str, char c) { - return std::count(str.begin(), str.end(), c); -} - class CookieMonsterTest : public testing::Test { public: CookieMonsterTest() : message_loop_(new base::MessageLoopForIO()) {} @@ -67,7 +63,7 @@ const std::string& cookie) { cm->SetCookieWithOptionsAsync( gurl, cookie, options_, - base::Bind(&SetCookieCallback::Run, base::Unretained(this))); + base::BindOnce(&SetCookieCallback::Run, base::Unretained(this))); WaitForCallback(); } @@ -79,22 +75,22 @@ CookieOptions options_; }; -class GetCookiesCallback : public CookieTestCallback { +class GetCookieListCallback : public CookieTestCallback { public: - const std::string& GetCookies(CookieMonster* cm, const GURL& gurl) { - cm->GetCookiesWithOptionsAsync( + const CookieList& GetCookieList(CookieMonster* cm, const GURL& gurl) { + cm->GetCookieListWithOptionsAsync( gurl, options_, - base::Bind(&GetCookiesCallback::Run, base::Unretained(this))); + base::BindOnce(&GetCookieListCallback::Run, base::Unretained(this))); WaitForCallback(); - return cookies_; + return cookie_list_; } private: - void Run(const std::string& cookies) { - cookies_ = cookies; + void Run(const CookieList& cookie_list) { + cookie_list_ = cookie_list; CookieTestCallback::Run(); } - std::string cookies_; + CookieList cookie_list_; CookieOptions options_; }; @@ -102,7 +98,7 @@ public: CookieList GetAllCookies(CookieMonster* cm) { cm->GetAllCookiesAsync( - base::Bind(&GetAllCookiesCallback::Run, base::Unretained(this))); + base::BindOnce(&GetAllCookiesCallback::Run, base::Unretained(this))); WaitForCallback(); return cookies_; } @@ -156,12 +152,12 @@ } timer.Done(); - GetCookiesCallback getCookiesCallback; + GetCookieListCallback getCookieListCallback; base::PerfTimeLogger timer2("Cookie_monster_query_single_host"); for (std::vector<std::string>::const_iterator it = cookies.begin(); it != cookies.end(); ++it) { - getCookiesCallback.GetCookies(cm.get(), GURL(kGoogleURL)); + getCookieListCallback.GetCookieList(cm.get(), GURL(kGoogleURL)); } timer2.Done(); @@ -189,12 +185,12 @@ } timer.Done(); - GetCookiesCallback getCookiesCallback; + GetCookieListCallback getCookieListCallback; base::PerfTimeLogger timer2("Cookie_monster_query_many_hosts"); for (std::vector<GURL>::const_iterator it = gurls.begin(); it != gurls.end(); ++it) { - getCookiesCallback.GetCookies(cm.get(), *it); + getCookieListCallback.GetCookieList(cm.get(), *it); } timer2.Done(); @@ -206,7 +202,7 @@ TEST_F(CookieMonsterTest, TestDomainTree) { std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr)); - GetCookiesCallback getCookiesCallback; + GetCookieListCallback getCookieListCallback; SetCookieCallback setCookieCallback; const char domain_cookie_format_tree[] = "a=b; domain=%s"; const std::string domain_base("top.com"); @@ -249,12 +245,13 @@ EXPECT_EQ(31u, getAllCookiesCallback.GetAllCookies(cm.get()).size()); GURL probe_gurl("https://b.a.b.a.top.com/"); - std::string cookie_line = getCookiesCallback.GetCookies(cm.get(), probe_gurl); - EXPECT_EQ(5, CountInString(cookie_line, '=')) - << "Cookie line: " << cookie_line; + const CookieList& cookie_list = + getCookieListCallback.GetCookieList(cm.get(), probe_gurl); + EXPECT_EQ(5u, cookie_list.size()) + << CanonicalCookie::BuildCookieLine(cookie_list); base::PerfTimeLogger timer("Cookie_monster_query_domain_tree"); for (int i = 0; i < kNumCookies; i++) { - getCookiesCallback.GetCookies(cm.get(), probe_gurl); + getCookieListCallback.GetCookieList(cm.get(), probe_gurl); } timer.Done(); } @@ -262,10 +259,9 @@ TEST_F(CookieMonsterTest, TestDomainLine) { std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr)); SetCookieCallback setCookieCallback; - GetCookiesCallback getCookiesCallback; + GetCookieListCallback getCookieListCallback; std::vector<std::string> domain_list; GURL probe_gurl("https://b.a.b.a.top.com/"); - std::string cookie_line; // Create a line of 32 domain cookies such that all cookies stored // by effective TLD+1 will apply to probe GURL. @@ -290,11 +286,12 @@ } } - cookie_line = getCookiesCallback.GetCookies(cm.get(), probe_gurl); - EXPECT_EQ(32, CountInString(cookie_line, '=')); + const CookieList& cookie_list = + getCookieListCallback.GetCookieList(cm.get(), probe_gurl); + EXPECT_EQ(32u, cookie_list.size()); base::PerfTimeLogger timer2("Cookie_monster_query_domain_line"); for (int i = 0; i < kNumCookies; i++) { - getCookiesCallback.GetCookies(cm.get(), probe_gurl); + getCookieListCallback.GetCookieList(cm.get(), probe_gurl); } timer2.Done(); } @@ -302,7 +299,7 @@ TEST_F(CookieMonsterTest, TestImport) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; - GetCookiesCallback getCookiesCallback; + GetCookieListCallback getCookieListCallback; // We want to setup a fairly large backing store, with 300 domains of 50 // cookies each. Creation times must be unique. @@ -327,7 +324,7 @@ GURL gurl("www.foo.com"); CookieOptions options; base::PerfTimeLogger timer("Cookie_monster_import_from_store"); - getCookiesCallback.GetCookies(cm.get(), gurl); + getCookieListCallback.GetCookieList(cm.get(), gurl); timer.Done(); // Just confirm keys were set as expected.
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index eeaed89..bc824e8 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -29,6 +29,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/cookies/canonical_cookie.h" +#include "net/cookies/canonical_cookie_test_helpers.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_monster_store_test.h" // For CookieStore mock #include "net/cookies/cookie_store_change_unittest.h" @@ -860,8 +861,6 @@ // TODO(erikwright): Replace the other callbacks and synchronous helper methods // in this test suite with these Mocks. using MockClosure = base::MockCallback<base::Closure>; -using MockGetCookiesCallback = - base::MockCallback<CookieStore::GetCookiesCallback>; using MockSetCookiesCallback = base::MockCallback<CookieStore::SetCookiesCallback>; using MockGetCookieListCallback = @@ -890,10 +889,6 @@ ACTION_P4(DeleteCookieAction, cookie_monster, url, name, callback) { cookie_monster->DeleteCookieAsync(url, name, callback->Get()); } -ACTION_P3(GetCookiesAction, cookie_monster, url, callback) { - cookie_monster->GetCookiesWithOptionsAsync(url, CookieOptions(), - callback->Get()); -} ACTION_P4(SetCookieAction, cookie_monster, url, cookie_line, callback) { cookie_monster->SetCookieWithOptionsAsync(url, cookie_line, CookieOptions(), callback->Get()); @@ -1055,24 +1050,27 @@ scoped_refptr<NewMockPersistentCookieStore> persistent_store_; }; -TEST_F(DeferredCookieTaskTest, DeferredGetCookies) { +TEST_F(DeferredCookieTaskTest, DeferredGetCookieList) { DeclareLoadedCookie(http_www_foo_.url(), "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", Time::Now() + TimeDelta::FromDays(3)); - MockGetCookiesCallback get_cookies_callback; + MockGetCookieListCallback get_cookie_list_callback; - BeginWithForDomainKey(http_www_foo_.domain(), - GetCookiesAction(&cookie_monster(), http_www_foo_.url(), - &get_cookies_callback)); + BeginWithForDomainKey( + http_www_foo_.domain(), + GetCookieListForUrlWithOptionsAction( + &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback)); WaitForLoadCall(); - EXPECT_CALL(get_cookies_callback, Run("X=1")) - .WillOnce(GetCookiesAction(&cookie_monster(), http_www_foo_.url(), - &get_cookies_callback)); + EXPECT_CALL(get_cookie_list_callback, Run(MatchesCookieLine("X=1"))) + .WillOnce(GetCookieListForUrlWithOptionsAction( + &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback)); + base::RunLoop loop; - EXPECT_CALL(get_cookies_callback, Run("X=1")).WillOnce(QuitRunLoop(&loop)); + EXPECT_CALL(get_cookie_list_callback, Run(MatchesCookieLine("X=1"))) + .WillOnce(QuitRunLoop(&loop)); CompleteLoading(); loop.Run(); @@ -1322,14 +1320,15 @@ "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", Time::Now() + TimeDelta::FromDays(3)); - MockGetCookiesCallback get_cookies_callback; + MockGetCookieListCallback get_cookie_list_callback; MockSetCookiesCallback set_cookies_callback; - MockGetCookiesCallback get_cookies_callback_deferred; + MockGetCookieListCallback get_cookie_list_callback_deferred; EXPECT_CALL(*this, Begin()) .WillOnce(testing::DoAll( - GetCookiesAction(&cookie_monster(), http_www_foo_.url(), - &get_cookies_callback), + GetCookieListForUrlWithOptionsAction(&cookie_monster(), + http_www_foo_.url(), + &get_cookie_list_callback), SetCookieAction(&cookie_monster(), http_www_foo_.url(), "A=B", &set_cookies_callback))); ExpectLoadCall(); @@ -1337,12 +1336,14 @@ Begin(); WaitForLoadCall(); - EXPECT_CALL(get_cookies_callback, Run("X=1")) - .WillOnce(GetCookiesAction(&cookie_monster(), http_www_foo_.url(), - &get_cookies_callback_deferred)); + EXPECT_CALL(get_cookie_list_callback, Run(MatchesCookieLine("X=1"))) + .WillOnce(GetCookieListForUrlWithOptionsAction( + &cookie_monster(), http_www_foo_.url(), + &get_cookie_list_callback_deferred)); EXPECT_CALL(set_cookies_callback, Run(true)); base::RunLoop loop; - EXPECT_CALL(get_cookies_callback_deferred, Run("A=B; X=1")) + EXPECT_CALL(get_cookie_list_callback_deferred, + Run(MatchesCookieLine("A=B; X=1"))) .WillOnce(QuitRunLoop(&loop)); CompleteLoading();
diff --git a/net/cookies/cookie_store.cc b/net/cookies/cookie_store.cc index 9190dfa..c3633d2 100644 --- a/net/cookies/cookie_store.cc +++ b/net/cookies/cookie_store.cc
@@ -16,23 +16,6 @@ return cause != CookieStore::ChangeCause::INSERTED; } -// Keep in sync with CanonicalCookie::BuildCookieLine. -std::string CookieStore::BuildCookieLine( - const std::vector<CanonicalCookie*>& cookies) { - std::string cookie_line; - for (auto* cookie : cookies) { - if (!cookie_line.empty()) - cookie_line += "; "; - // In Mozilla, if you set a cookie like "AAA", it will have an empty token - // and a value of "AAA". When it sends the cookie back, it will send "AAA", - // so we need to avoid sending "=AAA" for a blank token value. - if (!cookie->Name().empty()) - cookie_line += cookie->Name() + "="; - cookie_line += cookie->Value(); - } - return cookie_line; -} - void CookieStore::DeleteAllAsync(DeleteCallback callback) { DeleteAllCreatedBetweenAsync(base::Time(), base::Time::Max(), std::move(callback));
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h index 5a664d3..524b1a5 100644 --- a/net/cookies/cookie_store.h +++ b/net/cookies/cookie_store.h
@@ -60,8 +60,6 @@ // Callback definitions. typedef base::OnceCallback<void(const CookieList& cookies)> GetCookieListCallback; - typedef base::OnceCallback<void(const std::string& cookie)> - GetCookiesCallback; typedef base::OnceCallback<void(bool success)> SetCookiesCallback; typedef base::OnceCallback<void(uint32_t num_deleted)> DeleteCallback; @@ -79,16 +77,6 @@ virtual ~CookieStore(); - // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented - // by |cookies|. The string is built in the same order as the given list. - // - // Deprecated; use CanonicalCookie::BuildCookieLine( - // const std::vector<CanonicalCookie>& cookies) instead. - // TODO(http://crbug.com/588081#c3): Believed to only be used (directly - // and indirectly) by tests; should be removed. - static std::string BuildCookieLine( - const std::vector<CanonicalCookie*>& cookies); - // Sets the cookies specified by |cookie_list| returned from |url| // with options |options| in effect. Expects a cookie line, like // "a=1; domain=b.com". @@ -112,23 +100,6 @@ bool modify_http_only, SetCookiesCallback callback) = 0; - // TODO(???): what if the total size of all the cookies >4k, can we have a - // header that big or do we need multiple Cookie: headers? - // Note: Some sites, such as Facebook, occasionally use Cookie headers >4k. - // - // Simple interface, gets a cookie string "a=b; c=d" for the given URL. - // Gets all cookies that apply to |url| given |options|. Use options to - // access httponly cookies. - // - // The returned cookies are ordered by longest path, then earliest - // creation date. - // - // TODO(mkwst): This method is deprecated; callsites should be updated to - // use 'GetCookieListWithOptionsAsync'. - virtual void GetCookiesWithOptionsAsync(const GURL& url, - const CookieOptions& options, - GetCookiesCallback callback) = 0; - // Obtains a CookieList for the given |url| and |options|. The returned // cookies are passed into |callback|, ordered by longest path, then earliest // creation date.
diff --git a/net/cookies/cookie_store_test_callbacks.cc b/net/cookies/cookie_store_test_callbacks.cc index d37225a0..5e711d0a 100644 --- a/net/cookies/cookie_store_test_callbacks.cc +++ b/net/cookies/cookie_store_test_callbacks.cc
@@ -38,11 +38,6 @@ loop_to_quit_.Run(); } -StringResultCookieCallback::StringResultCookieCallback() = default; -StringResultCookieCallback::StringResultCookieCallback( - base::Thread* run_in_thread) - : CookieCallback(run_in_thread) {} - NoResultCookieCallback::NoResultCookieCallback() = default; NoResultCookieCallback::NoResultCookieCallback(base::Thread* run_in_thread) : CookieCallback(run_in_thread) {}
diff --git a/net/cookies/cookie_store_test_callbacks.h b/net/cookies/cookie_store_test_callbacks.h index 207eb02..d126ea715 100644 --- a/net/cookies/cookie_store_test_callbacks.h +++ b/net/cookies/cookie_store_test_callbacks.h
@@ -69,22 +69,6 @@ T result_; }; -class StringResultCookieCallback : public CookieCallback { - public: - StringResultCookieCallback(); - explicit StringResultCookieCallback(base::Thread* run_in_thread); - - void Run(const std::string& result) { - result_ = result; - CallbackEpilogue(); - } - - const std::string& result() { return result_; } - - private: - std::string result_; -}; - class NoResultCookieCallback : public CookieCallback { public: NoResultCookieCallback();
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc index 0f408fd..e126521 100644 --- a/net/cookies/cookie_store_test_helpers.cc +++ b/net/cookies/cookie_store_test_helpers.cc
@@ -45,12 +45,6 @@ did_run_ = true; } -void DelayedCookieMonster::GetCookiesWithOptionsInternalCallback( - const std::string& cookie) { - cookie_ = cookie; - did_run_ = true; -} - void DelayedCookieMonster::GetCookieListWithOptionsInternalCallback( const CookieList& cookie_list) { cookie_list_ = cookie_list; @@ -93,23 +87,6 @@ base::TimeDelta::FromMilliseconds(kDelayedTime)); } -void DelayedCookieMonster::GetCookiesWithOptionsAsync( - const GURL& url, - const CookieOptions& options, - CookieMonster::GetCookiesCallback callback) { - did_run_ = false; - cookie_monster_->GetCookiesWithOptionsAsync( - url, options, - base::Bind(&DelayedCookieMonster::GetCookiesWithOptionsInternalCallback, - base::Unretained(this))); - DCHECK_EQ(did_run_, true); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&DelayedCookieMonster::InvokeGetCookieStringCallback, - base::Unretained(this), std::move(callback)), - base::TimeDelta::FromMilliseconds(kDelayedTime)); -} - void DelayedCookieMonster::GetCookieListWithOptionsAsync( const GURL& url, const CookieOptions& options, @@ -138,12 +115,6 @@ std::move(callback).Run(result_); } -void DelayedCookieMonster::InvokeGetCookieStringCallback( - CookieMonster::GetCookiesCallback callback) { - if (!callback.is_null()) - std::move(callback).Run(cookie_); -} - void DelayedCookieMonster::InvokeGetCookieListCallback( CookieMonster::GetCookieListCallback callback) { if (!callback.is_null()) @@ -158,13 +129,6 @@ return false; } -std::string DelayedCookieMonster::GetCookiesWithOptions( - const GURL& url, - const CookieOptions& options) { - ADD_FAILURE(); - return std::string(); -} - void DelayedCookieMonster::DeleteCookie(const GURL& url, const std::string& cookie_name) { ADD_FAILURE();
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h index 3c1c8572..ba4cc1f 100644 --- a/net/cookies/cookie_store_test_helpers.h +++ b/net/cookies/cookie_store_test_helpers.h
@@ -36,11 +36,6 @@ bool modify_http_only, SetCookiesCallback callback) override; - void GetCookiesWithOptionsAsync( - const GURL& url, - const CookieOptions& options, - CookieMonster::GetCookiesCallback callback) override; - void GetCookieListWithOptionsAsync(const GURL& url, const CookieOptions& options, GetCookieListCallback callback) override; @@ -51,9 +46,6 @@ const std::string& cookie_line, const CookieOptions& options); - virtual std::string GetCookiesWithOptions(const GURL& url, - const CookieOptions& options); - virtual void DeleteCookie(const GURL& url, const std::string& cookie_name); @@ -100,9 +92,6 @@ void InvokeSetCookiesCallback(CookieMonster::SetCookiesCallback callback); - void InvokeGetCookieStringCallback( - CookieMonster::GetCookiesCallback callback); - void InvokeGetCookieListCallback( CookieMonster::GetCookieListCallback callback);
diff --git a/net/cookies/cookie_store_unittest.cc b/net/cookies/cookie_store_unittest.cc deleted file mode 100644 index ec43b34..0000000 --- a/net/cookies/cookie_store_unittest.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/cookies/cookie_store.h" - -#include <memory> -#include <vector> - -#include "base/time/time.h" -#include "net/cookies/canonical_cookie.h" -#include "net/cookies/cookie_options.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace net { - -namespace { - -// Helper for testing BuildCookieLine -void MatchCookieLineToVector( - const std::string& line, - const std::vector<std::unique_ptr<CanonicalCookie>>& cookies) { - // Test the std::vector<CanonicalCookie*> variant - // ('CookieMonster::CanonicalCookieVector' (yes, this is absurd)): - std::vector<CanonicalCookie*> ptr_list; - for (const auto& cookie : cookies) - ptr_list.push_back(cookie.get()); - EXPECT_EQ(line, CookieStore::BuildCookieLine(ptr_list)); -} - -} // namespace - -// TODO(rdsmith): Keep in sync with CanonicalCookieTest.BuildCookieLine; -// remove when the need for CookieStore::BuildCookieLine is done. -TEST(CookieStoreBaseTest, BuildCookieLine) { - std::vector<std::unique_ptr<CanonicalCookie>> cookies; - GURL url("https://example.com/"); - CookieOptions options; - base::Time now = base::Time::Now(); - MatchCookieLineToVector("", cookies); - - cookies.push_back(CanonicalCookie::Create(url, "A=B", now, options)); - MatchCookieLineToVector("A=B", cookies); - // Nameless cookies are sent back without a prefixed '='. - cookies.push_back(CanonicalCookie::Create(url, "C", now, options)); - MatchCookieLineToVector("A=B; C", cookies); - // Cookies separated by ';'. - cookies.push_back(CanonicalCookie::Create(url, "D=E", now, options)); - MatchCookieLineToVector("A=B; C; D=E", cookies); - // BuildCookieLine doesn't reorder the list, it relies on the caller to do so. - cookies.push_back(CanonicalCookie::Create( - url, "F=G", now - base::TimeDelta::FromSeconds(1), options)); - MatchCookieLineToVector("A=B; C; D=E; F=G", cookies); - // BuildCookieLine doesn't deduplicate. - cookies.push_back(CanonicalCookie::Create( - url, "D=E", now - base::TimeDelta::FromSeconds(2), options)); - MatchCookieLineToVector("A=B; C; D=E; F=G; D=E", cookies); -} - -} // namespace net
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h index def6b75..1d36cbe 100644 --- a/net/cookies/cookie_store_unittest.h +++ b/net/cookies/cookie_store_unittest.h
@@ -1338,7 +1338,7 @@ EXPECT_EQ(2u, // Deletes A=B, E=B this->DeleteAllCreatedBetweenWithPredicate( cs, now, base::Time::Max(), - base::Bind(&CookieHasValue, desired_value))); + base::BindRepeating(&CookieHasValue, desired_value))); // Check that we deleted the right ones. this->MatchCookieLines("C=D;Y=Z", @@ -1353,13 +1353,13 @@ desired_value = "D"; EXPECT_EQ(0u, this->DeleteAllCreatedBetweenWithPredicate( cs, last_month, last_minute, - base::Bind(&CookieHasValue, desired_value))); + base::BindRepeating(&CookieHasValue, desired_value))); this->MatchCookieLines("C=D;Y=Z", this->GetCookies(cs, this->https_www_foo_.url())); // Same thing, but with a good time range. EXPECT_EQ(1u, this->DeleteAllCreatedBetweenWithPredicate( cs, now, base::Time::Max(), - base::Bind(&CookieHasValue, desired_value))); + base::BindRepeating(&CookieHasValue, desired_value))); this->MatchCookieLines("Y=Z", this->GetCookies(cs, this->https_www_foo_.url())); }
diff --git a/net/data/ssl/ev_roots/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem b/net/data/ssl/ev_roots/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem new file mode 100644 index 0000000..cd2715a6 --- /dev/null +++ b/net/data/ssl/ev_roots/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem
@@ -0,0 +1,52 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 05:55:56:bc:f2:5e:a4:35:35:c3:a4:0f:d5:ab:45:72 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:dd:a7:d9:bb:8a:b8:0b:fb:0b:7f:21:d2:f0:be: + be:73:f3:33:5d:1a:bc:34:ea:de:c6:9b:bc:d0:95: + f6:f0:cc:d0:0b:ba:61:5b:51:46:7e:9e:2d:9f:ee: + 8e:63:0c:17:ec:07:70:f5:cf:84:2e:40:83:9c:e8: + 3f:41:6d:3b:ad:d3:a4:14:59:36:78:9d:03:43:ee: + 10:13:6c:72:de:ae:88:a7:a1:6b:b5:43:ce:67:dc: + 23:ff:03:1c:a3:e2:3e + ASN1 OID: secp384r1 + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + B3:DB:48:A4:F9:A1:C5:D8:AE:36:41:CC:11:63:69:62:29:BC:4B:C6 + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:ad:bc:f2:6c:3f:12:4a:d1:2d:39:c3:0a:09: + 97:73:f4:88:36:8c:88:27:bb:e6:88:8d:50:85:a7:63:f9:9e: + 32:de:66:93:0f:f1:cc:b1:09:8f:dd:6c:ab:fa:6b:7f:a0:02: + 30:39:66:5b:c2:64:8d:b8:9e:50:dc:a8:d5:49:a2:ed:c7:dc: + d1:49:7f:17:01:b8:c8:86:8f:4e:8c:88:2b:a8:9a:a9:8a:c5: + d1:00:bd:f8:54:e2:9a:e5:5b:7c:b3:27:17 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE-----
diff --git a/net/data/ssl/ev_roots/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem b/net/data/ssl/ev_roots/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem new file mode 100644 index 0000000..6f24469 --- /dev/null +++ b/net/data/ssl/ev_roots/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem
@@ -0,0 +1,82 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA + Validity + Not Before: Nov 10 00:00:00 2006 GMT + Not After : Nov 10 00:00:00 2031 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ad:0e:15:ce:e4:43:80:5c:b1:87:f3:b7:60:f9: + 71:12:a5:ae:dc:26:94:88:aa:f4:ce:f5:20:39:28: + 58:60:0c:f8:80:da:a9:15:95:32:61:3c:b5:b1:28: + 84:8a:8a:dc:9f:0a:0c:83:17:7a:8f:90:ac:8a:e7: + 79:53:5c:31:84:2a:f6:0f:98:32:36:76:cc:de:dd: + 3c:a8:a2:ef:6a:fb:21:f2:52:61:df:9f:20:d7:1f: + e2:b1:d9:fe:18:64:d2:12:5b:5f:f9:58:18:35:bc: + 47:cd:a1:36:f9:6b:7f:d4:b0:38:3e:c1:1b:c3:8c: + 33:d9:d8:2f:18:fe:28:0f:b3:a7:83:d6:c3:6e:44: + c0:61:35:96:16:fe:59:9c:8b:76:6d:d7:f1:a2:4b: + 0d:2b:ff:0b:72:da:9e:60:d0:8e:90:35:c6:78:55: + 87:20:a1:cf:e5:6d:0a:c8:49:7c:31:98:33:6c:22: + e9:87:d0:32:5a:a2:ba:13:82:11:ed:39:17:9d:99: + 3a:72:a1:e6:fa:a4:d9:d5:17:31:75:ae:85:7d:22: + ae:3f:01:46:86:f6:28:79:c8:b1:da:e4:57:17:c4: + 7e:1c:0e:b0:b4:92:a6:56:b3:bd:b2:97:ed:aa:a7: + f0:b7:c5:a8:3f:95:16:d0:ff:a1:96:eb:08:5f:18: + 77:4f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F + X509v3 Authority Key Identifier: + keyid:45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F + + Signature Algorithm: sha1WithRSAEncryption + a2:0e:bc:df:e2:ed:f0:e3:72:73:7a:64:94:bf:f7:72:66:d8: + 32:e4:42:75:62:ae:87:eb:f2:d5:d9:de:56:b3:9f:cc:ce:14: + 28:b9:0d:97:60:5c:12:4c:58:e4:d3:3d:83:49:45:58:97:35: + 69:1a:a8:47:ea:56:c6:79:ab:12:d8:67:81:84:df:7f:09:3c: + 94:e6:b8:26:2c:20:bd:3d:b3:28:89:f7:5f:ff:22:e2:97:84: + 1f:e9:65:ef:87:e0:df:c1:67:49:b3:5d:eb:b2:09:2a:eb:26: + ed:78:be:7d:3f:2b:f3:b7:26:35:6d:5f:89:01:b6:49:5b:9f: + 01:05:9b:ab:3d:25:c1:cc:b6:7f:c2:f1:6f:86:c6:fa:64:68: + eb:81:2d:94:eb:42:b7:fa:8c:1e:dd:62:f1:be:50:67:b7:6c: + bd:f3:f1:1f:6b:0c:36:07:16:7f:37:7c:a9:5b:6d:7a:f1:12: + 46:60:83:d7:27:04:be:4b:ce:97:be:c3:67:2a:68:11:df:80: + e7:0c:33:66:bf:13:0d:14:6e:f3:7f:1f:63:10:1e:fa:8d:1b: + 25:6d:6c:8f:a5:b7:61:01:b1:d2:a3:26:a1:10:71:9d:ad:e2: + c3:f9:c3:99:51:b7:2b:07:08:ce:2e:e6:50:b2:a7:fa:0a:45: + 2f:a2:f0:f2 +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE-----
diff --git a/net/data/ssl/ev_roots/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem b/net/data/ssl/ev_roots/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem new file mode 100644 index 0000000..39335e77 --- /dev/null +++ b/net/data/ssl/ev_roots/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem
@@ -0,0 +1,82 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA + Validity + Not Before: Nov 10 00:00:00 2006 GMT + Not After : Nov 10 00:00:00 2031 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e2:3b:e1:11:72:de:a8:a4:d3:a3:57:aa:50:a2: + 8f:0b:77:90:c9:a2:a5:ee:12:ce:96:5b:01:09:20: + cc:01:93:a7:4e:30:b7:53:f7:43:c4:69:00:57:9d: + e2:8d:22:dd:87:06:40:00:81:09:ce:ce:1b:83:bf: + df:cd:3b:71:46:e2:d6:66:c7:05:b3:76:27:16:8f: + 7b:9e:1e:95:7d:ee:b7:48:a3:08:da:d6:af:7a:0c: + 39:06:65:7f:4a:5d:1f:bc:17:f8:ab:be:ee:28:d7: + 74:7f:7a:78:99:59:85:68:6e:5c:23:32:4b:bf:4e: + c0:e8:5a:6d:e3:70:bf:77:10:bf:fc:01:f6:85:d9: + a8:44:10:58:32:a9:75:18:d5:d1:a2:be:47:e2:27: + 6a:f4:9a:33:f8:49:08:60:8b:d4:5f:b4:3a:84:bf: + a1:aa:4a:4c:7d:3e:cf:4f:5f:6c:76:5e:a0:4b:37: + 91:9e:dc:22:e6:6d:ce:14:1a:8e:6a:cb:fe:cd:b3: + 14:64:17:c7:5b:29:9e:32:bf:f2:ee:fa:d3:0b:42: + d4:ab:b7:41:32:da:0c:d4:ef:f8:81:d5:bb:8d:58: + 3f:b5:1b:e8:49:28:a2:70:da:31:04:dd:f7:b2:16: + f2:4c:0a:4e:07:a8:ed:4a:3d:5e:b5:7f:a3:90:c3: + af:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55 + X509v3 Authority Key Identifier: + keyid:03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55 + + Signature Algorithm: sha1WithRSAEncryption + cb:9c:37:aa:48:13:12:0a:fa:dd:44:9c:4f:52:b0:f4:df:ae: + 04:f5:79:79:08:a3:24:18:fc:4b:2b:84:c0:2d:b9:d5:c7:fe: + f4:c1:1f:58:cb:b8:6d:9c:7a:74:e7:98:29:ab:11:b5:e3:70: + a0:a1:cd:4c:88:99:93:8c:91:70:e2:ab:0f:1c:be:93:a9:ff: + 63:d5:e4:07:60:d3:a3:bf:9d:5b:09:f1:d5:8e:e3:53:f4:8e: + 63:fa:3f:a7:db:b4:66:df:62:66:d6:d1:6e:41:8d:f2:2d:b5: + ea:77:4a:9f:9d:58:e2:2b:59:c0:40:23:ed:2d:28:82:45:3e: + 79:54:92:26:98:e0:80:48:a8:37:ef:f0:d6:79:60:16:de:ac: + e8:0e:cd:6e:ac:44:17:38:2f:49:da:e1:45:3e:2a:b9:36:53: + cf:3a:50:06:f7:2e:e8:c4:57:49:6c:61:21:18:d5:04:ad:78: + 3c:2c:3a:80:6b:a7:eb:af:15:14:e9:d8:89:c1:b9:38:6c:e2: + 91:6c:8a:ff:64:b9:77:25:57:30:c0:1b:24:a3:e1:dc:e9:df: + 47:7c:b5:b4:24:08:05:30:ec:2d:bd:0b:bf:45:bf:50:b9:a9: + f3:eb:98:01:12:ad:c8:88:c6:98:34:5f:8d:0a:3c:c6:e9:d5: + 95:95:6d:de +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE-----
diff --git a/net/data/ssl/ev_roots/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem b/net/data/ssl/ev_roots/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem new file mode 100644 index 0000000..fb8abc8 --- /dev/null +++ b/net/data/ssl/ev_roots/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem
@@ -0,0 +1,120 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 05:9b:1b:57:9e:8e:21:32:e2:39:07:bd:a7:77:75:5c + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Trusted Root G4 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Trusted Root G4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:bf:e6:90:73:68:de:bb:e4:5d:4a:3c:30:22:30: + 69:33:ec:c2:a7:25:2e:c9:21:3d:f2:8a:d8:59:c2: + e1:29:a7:3d:58:ab:76:9a:cd:ae:7b:1b:84:0d:c4: + 30:1f:f3:1b:a4:38:16:eb:56:c6:97:6d:1d:ab:b2: + 79:f2:ca:11:d2:e4:5f:d6:05:3c:52:0f:52:1f:c6: + 9e:15:a5:7e:be:9f:a9:57:16:59:55:72:af:68:93: + 70:c2:b2:ba:75:99:6a:73:32:94:d1:10:44:10:2e: + df:82:f3:07:84:e6:74:3b:6d:71:e2:2d:0c:1b:ee: + 20:d5:c9:20:1d:63:29:2d:ce:ec:5e:4e:c8:93:f8: + 21:61:9b:34:eb:05:c6:5e:ec:5b:1a:bc:eb:c9:cf: + cd:ac:34:40:5f:b1:7a:66:ee:77:c8:48:a8:66:57: + 57:9f:54:58:8e:0c:2b:b7:4f:a7:30:d9:56:ee:ca: + 7b:5d:e3:ad:c9:4f:5e:e5:35:e7:31:cb:da:93:5e: + dc:8e:8f:80:da:b6:91:98:40:90:79:c3:78:c7:b6: + b1:c4:b5:6a:18:38:03:10:8d:d8:d4:37:a4:2e:05: + 7d:88:f5:82:3e:10:91:70:ab:55:82:41:32:d7:db: + 04:73:2a:6e:91:01:7c:21:4c:d4:bc:ae:1b:03:75: + 5d:78:66:d9:3a:31:44:9a:33:40:bf:08:d7:5a:49: + a4:c2:e6:a9:a0:67:dd:a4:27:bc:a1:4f:39:b5:11: + 58:17:f7:24:5c:46:8f:64:f7:c1:69:88:76:98:76: + 3d:59:5d:42:76:87:89:97:69:7a:48:f0:e0:a2:12: + 1b:66:9a:74:ca:de:4b:1e:e7:0e:63:ae:e6:d4:ef: + 92:92:3a:9e:3d:dc:00:e4:45:25:89:b6:9a:44:19: + 2b:7e:c0:94:b4:d2:61:6d:eb:33:d9:c5:df:4b:04: + 00:cc:7d:1c:95:c3:8f:f7:21:b2:b2:11:b7:bb:7f: + f2:d5:8c:70:2c:41:60:aa:b1:63:18:44:95:1a:76: + 62:7e:f6:80:b0:fb:e8:64:a6:33:d1:89:07:e1:bd: + b7:e6:43:a4:18:b8:a6:77:01:e1:0f:94:0c:21:1d: + b2:54:29:25:89:6c:e5:0e:52:51:47:74:be:26:ac: + b6:41:75:de:7a:ac:5f:8d:3f:c9:bc:d3:41:11:12: + 5b:e5:10:50:eb:31:c5:ca:72:16:22:09:df:7c:4c: + 75:3f:63:ec:21:5f:c4:20:51:6b:6f:b1:ab:86:8b: + 4f:c2:d6:45:5f:9d:20:fc:a1:1e:c5:c0:8f:a2:b1: + 7e:0a:26:99:f5:e4:69:2f:98:1d:2d:f5:d9:a9:b2: + 1d:e5:1b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + EC:D7:E3:82:D2:71:5D:64:4C:DF:2E:67:3F:E7:BA:98:AE:1C:0F:4F + Signature Algorithm: sha384WithRSAEncryption + bb:61:d9:7d:a9:6c:be:17:c4:91:1b:c3:a1:a2:00:8d:e3:64: + 68:0f:56:cf:77:ae:70:f9:fd:9a:4a:99:b9:c9:78:5c:0c:0c: + 5f:e4:e6:14:29:56:0b:36:49:5d:44:63:e0:ad:9c:96:18:66: + 1b:23:0d:3d:79:e9:6d:6b:d6:54:f8:d2:3c:c1:43:40:ae:1d: + 50:f5:52:fc:90:3b:bb:98:99:69:6b:c7:c1:a7:a8:68:a4:27: + dc:9d:f9:27:ae:30:85:b9:f6:67:4d:3a:3e:8f:59:39:22:53: + 44:eb:c8:5d:03:ca:ed:50:7a:7d:62:21:0a:80:c8:73:66:d1: + a0:05:60:5f:e8:a5:b4:a7:af:a8:f7:6d:35:9c:7c:5a:8a:d6: + a2:38:99:f3:78:8b:f4:4d:d2:20:0b:de:04:ee:8c:9b:47:81: + 72:0d:c0:14:32:ef:30:59:2e:ae:e0:71:f2:56:e4:6a:97:6f: + 92:50:6d:96:8d:68:7a:9a:b2:36:14:7a:06:f2:24:b9:09:11: + 50:d7:08:b1:b8:89:7a:84:23:61:42:29:e5:a3:cd:a2:20:41: + d7:d1:9c:64:d9:ea:26:a1:8b:14:d7:4c:19:b2:50:41:71:3d: + 3f:4d:70:23:86:0c:4a:dc:81:d2:cc:32:94:84:0d:08:09:97: + 1c:4f:c0:ee:6b:20:74:30:d2:e0:39:34:10:85:21:15:01:08: + e8:55:32:de:71:49:d9:28:17:50:4d:e6:be:4d:d1:75:ac:d0: + ca:fb:41:b8:43:a5:aa:d3:c3:05:44:4f:2c:36:9b:e2:fa:e2: + 45:b8:23:53:6c:06:6f:67:55:7f:46:b5:4c:3f:6e:28:5a:79: + 26:d2:a4:a8:62:97:d2:1e:e2:ed:4a:8b:bc:1b:fd:47:4a:0d: + df:67:66:7e:b2:5b:41:d0:3b:e4:f4:3b:f4:04:63:e9:ef:c2: + 54:00:51:a0:8a:2a:c9:ce:78:cc:d5:ea:87:04:18:b3:ce:af: + 49:88:af:f3:92:99:b6:b3:e6:61:0f:d2:85:00:e7:50:1a:e4: + 1b:95:9d:19:a1:b9:9c:b1:9b:b1:00:1e:ef:d0:0f:4f:42:6c: + c9:0a:bc:ee:43:fa:3a:71:a5:c8:4d:26:a5:35:fd:89:5d:bc: + 85:62:1d:32:d2:a0:2b:54:ed:9a:57:c1:db:fa:10:cf:19:b7: + 8b:4a:1b:8f:01:b6:27:95:53:e8:b6:89:6d:5b:bc:68:d4:23: + e8:8b:51:a2:56:f9:f0:a6:80:a0:d6:1e:b3:bc:0f:0f:53:75: + 29:aa:ea:13:77:e4:de:8c:81:21:ad:07:10:47:11:ad:87:3d: + 07:d1:75:bc:cf:f3:66:7e +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE-----
diff --git a/net/data/ssl/ev_roots/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem b/net/data/ssl/ev_roots/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem new file mode 100644 index 0000000..2fb401c --- /dev/null +++ b/net/data/ssl/ev_roots/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem
@@ -0,0 +1,79 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 03:3a:f1:e6:a7:11:a9:a0:bb:28:64:b1:1d:09:fa:e5 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2 + Validity + Not Before: Aug 1 12:00:00 2013 GMT + Not After : Jan 15 12:00:00 2038 GMT + Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bb:37:cd:34:dc:7b:6b:c9:b2:68:90:ad:4a:75: + ff:46:ba:21:0a:08:8d:f5:19:54:c9:fb:88:db:f3: + ae:f2:3a:89:91:3c:7a:e6:ab:06:1a:6b:cf:ac:2d: + e8:5e:09:24:44:ba:62:9a:7e:d6:a3:a8:7e:e0:54: + 75:20:05:ac:50:b7:9c:63:1a:6c:30:dc:da:1f:19: + b1:d7:1e:de:fd:d7:e0:cb:94:83:37:ae:ec:1f:43: + 4e:dd:7b:2c:d2:bd:2e:a5:2f:e4:a9:b8:ad:3a:d4: + 99:a4:b6:25:e9:9b:6b:00:60:92:60:ff:4f:21:49: + 18:f7:67:90:ab:61:06:9c:8f:f2:ba:e9:b4:e9:92: + 32:6b:b5:f3:57:e8:5d:1b:cd:8c:1d:ab:95:04:95: + 49:f3:35:2d:96:e3:49:6d:dd:77:e3:fb:49:4b:b4: + ac:55:07:a9:8f:95:b3:b4:23:bb:4c:6d:45:f0:f6: + a9:b2:95:30:b4:fd:4c:55:8c:27:4a:57:14:7c:82: + 9d:cd:73:92:d3:16:4a:06:0c:8c:50:d1:8f:1e:09: + be:17:a1:e6:21:ca:fd:83:e5:10:bc:83:a5:0a:c4: + 67:28:f6:73:14:14:3d:46:76:c3:87:14:89:21:34: + 4d:af:0f:45:0c:a6:49:a1:ba:bb:9c:c5:b1:33:83: + 29:85 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 4E:22:54:20:18:95:E6:E3:6E:E6:0F:FA:FA:B9:12:ED:06:17:8F:39 + Signature Algorithm: sha256WithRSAEncryption + 60:67:28:94:6f:0e:48:63:eb:31:dd:ea:67:18:d5:89:7d:3c: + c5:8b:4a:7f:e9:be:db:2b:17:df:b0:5f:73:77:2a:32:13:39: + 81:67:42:84:23:f2:45:67:35:ec:88:bf:f8:8f:b0:61:0c:34: + a4:ae:20:4c:84:c6:db:f8:35:e1:76:d9:df:a6:42:bb:c7:44: + 08:86:7f:36:74:24:5a:da:6c:0d:14:59:35:bd:f2:49:dd:b6: + 1f:c9:b3:0d:47:2a:3d:99:2f:bb:5c:bb:b5:d4:20:e1:99:5f: + 53:46:15:db:68:9b:f0:f3:30:d5:3e:31:e2:8d:84:9e:e3:8a: + da:da:96:3e:35:13:a5:5f:f0:f9:70:50:70:47:41:11:57:19: + 4e:c0:8f:ae:06:c4:95:13:17:2f:1b:25:9f:75:f2:b1:8e:99: + a1:6f:13:b1:41:71:fe:88:2a:c8:4f:10:20:55:d7:f3:14:45: + e5:e0:44:f4:ea:87:95:32:93:0e:fe:53:46:fa:2c:9d:ff:8b: + 22:b9:4b:d9:09:45:a4:de:a4:b8:9a:58:dd:1b:7d:52:9f:8e: + 59:43:88:81:a4:9e:26:d5:6f:ad:dd:0d:c6:37:7d:ed:03:92: + 1b:e5:77:5f:76:ee:3c:8d:c4:5d:56:5b:a2:d9:66:6e:b3:35: + 37:e5:32:b6 +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE-----
diff --git a/net/nqe/network_quality_store.cc b/net/nqe/network_quality_store.cc index 6d85622..0b3d2a97 100644 --- a/net/nqe/network_quality_store.cc +++ b/net/nqe/network_quality_store.cc
@@ -70,13 +70,7 @@ nqe::internal::CachedNetworkQuality* cached_network_quality) const { DCHECK(thread_checker_.CalledOnValidThread()); - // |matching_it| points to the entry that has the same connection type and - // id as |network_id|, and has the signal strength closest to the signal - // stength of |network_id|. - CachedNetworkQualities::const_iterator matching_it = - cached_network_qualities_.end(); - int matching_it_diff_signal_strength = INT32_MAX; - + // First check if an exact match can be found. for (CachedNetworkQualities::const_iterator it = cached_network_qualities_.begin(); it != cached_network_qualities_.end(); ++it) { @@ -85,20 +79,85 @@ continue; } - if (network_id.signal_strength == INT32_MIN) { - // Current network does not have a valid signal strength value. Return the - // entry without searching for the entry with the closest signal strength. - matching_it = it; - break; + // Check for an exact match, and return immediately if one is found. + // It's possible that the current network does not have signal strength + // available. In that case, return the cached network quality when the + // signal strength was unavailable. + if (network_id.signal_strength == it->first.signal_strength) { + *cached_network_quality = it->second; + return true; } + } + + // Handle the case when current network does not have signal strength + // available. Return the cached network quality that corresponds to the + // highest signal strength. This ensures that the method returns the fastest + // network quality possible for the current network, and serves as a + // conservative estimate. + if (network_id.signal_strength == INT32_MIN) { + CachedNetworkQualities::const_iterator matching_it = + cached_network_qualities_.end(); + + for (CachedNetworkQualities::const_iterator it = + cached_network_qualities_.begin(); + it != cached_network_qualities_.end(); ++it) { + if (network_id.type != it->first.type || network_id.id != it->first.id) { + // The |type| and |id| must match. + continue; + } + + // The cached network must have signal strength available. If the cached + // signal strength is unavailable, then this case would have been handled + // above. + DCHECK_NE(INT32_MIN, it->first.signal_strength); + + if (matching_it == cached_network_qualities_.end() || + it->first.signal_strength > matching_it->first.signal_strength) { + matching_it = it; + } + } + + if (matching_it == cached_network_qualities_.end()) + return false; + + *cached_network_quality = matching_it->second; + return true; + } + + // Finally, handle the case where the current network has a valid signal + // strength, but there is no exact match. + + // |matching_it| points to the entry that has the same connection type and + // id as |network_id|, and has the signal strength closest to the signal + // stength of |network_id|. + CachedNetworkQualities::const_iterator matching_it = + cached_network_qualities_.end(); + int matching_it_diff_signal_strength = INT32_MAX; + + // Find the closest estimate. + for (CachedNetworkQualities::const_iterator it = + cached_network_qualities_.begin(); + it != cached_network_qualities_.end(); ++it) { + if (network_id.type != it->first.type || network_id.id != it->first.id) { + // The |type| and |id| must match. + continue; + } + + DCHECK_LE(0, network_id.signal_strength); // Determine if the signal strength of |network_id| is closer to the // signal strength of the network at |it| then that of the network at // |matching_it|. int diff_signal_strength = std::abs(network_id.signal_strength - it->first.signal_strength); - if (it->first.signal_strength == INT32_MIN) + if (it->first.signal_strength == INT32_MIN) { + // Current network has signal strength available. However, the persisted + // network does not. Set the |diff_signal_strength| to INT32_MAX. This + // ensures that if an entry with a valid signal strength is found later + // during iteration, then that entry will be used. If no entry with valid + // signal strength is found, then this entry will be used. diff_signal_strength = INT32_MAX; + } if (matching_it == cached_network_qualities_.end() || diff_signal_strength < matching_it_diff_signal_strength) {
diff --git a/net/nqe/network_quality_store_unittest.cc b/net/nqe/network_quality_store_unittest.cc index 12928c50..b1b5665 100644 --- a/net/nqe/network_quality_store_unittest.cc +++ b/net/nqe/network_quality_store_unittest.cc
@@ -204,18 +204,19 @@ } { - // Existing entry will be read for (2G, "test1", INT32_MIN). - // The first entry in the store matching (2G, "test1", *) would be returned. + // When the current network does not have signal strength available, then + // the cached value that corresponds to maximum signal strength should be + // returned. int32_t signal_strength = INT32_MIN; + nqe::internal::CachedNetworkQuality expected_cached_network_quality = + cached_network_quality_strength_3; nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G, "test1", signal_strength); nqe::internal::CachedNetworkQuality read_network_quality; EXPECT_TRUE( network_quality_store.GetById(network_id, &read_network_quality)); - EXPECT_TRUE((cached_network_quality_strength_1.network_quality() == - read_network_quality.network_quality()) || - (cached_network_quality_strength_3.network_quality() == - read_network_quality.network_quality())); + EXPECT_EQ(expected_cached_network_quality.network_quality(), + read_network_quality.network_quality()); } { @@ -227,6 +228,85 @@ network_quality_store.GetById(network_id, &read_network_quality)); } } + +TEST(NetworkQualityStoreTest, TestCachingUnknownSignalStrength) { + nqe::internal::NetworkQualityStore network_quality_store; + base::SimpleTestTickClock tick_clock; + + // Cached network quality for network with NetworkID (2G, "test1"). + const nqe::internal::CachedNetworkQuality + cached_network_quality_strength_unknown( + tick_clock.NowTicks(), + nqe::internal::NetworkQuality(base::TimeDelta::FromSeconds(1), + base::TimeDelta::FromSeconds(1), 1), + EFFECTIVE_CONNECTION_TYPE_2G); + + const nqe::internal::CachedNetworkQuality cached_network_quality_strength_3( + tick_clock.NowTicks(), + nqe::internal::NetworkQuality(base::TimeDelta::FromSeconds(3), + base::TimeDelta::FromSeconds(3), 3), + EFFECTIVE_CONNECTION_TYPE_2G); + + { + // Entry will be added for (2G, "test1") with signal strength value of + // INT32_MIN. + nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G, + "test1", INT32_MIN); + nqe::internal::CachedNetworkQuality read_network_quality; + network_quality_store.Add(network_id, + cached_network_quality_strength_unknown); + EXPECT_TRUE( + network_quality_store.GetById(network_id, &read_network_quality)); + EXPECT_EQ(cached_network_quality_strength_unknown.network_quality(), + read_network_quality.network_quality()); + } + + { + // Entry will be added for (2G, "test1") with signal strength value of 3. + nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G, + "test1", 3); + nqe::internal::CachedNetworkQuality read_network_quality; + network_quality_store.Add(network_id, cached_network_quality_strength_3); + EXPECT_TRUE( + network_quality_store.GetById(network_id, &read_network_quality)); + EXPECT_EQ(cached_network_quality_strength_3.network_quality(), + read_network_quality.network_quality()); + } + + { + // Now with cached entries for signal strengths INT32_MIN and 3, verify + // across the range of strength values that the closest value match will be + // returned when looking up (2G, "test1", signal_strength). + for (int32_t signal_strength = 0; signal_strength <= 4; ++signal_strength) { + nqe::internal::CachedNetworkQuality expected_cached_network_quality = + cached_network_quality_strength_3; + nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G, + "test1", signal_strength); + nqe::internal::CachedNetworkQuality read_network_quality; + EXPECT_TRUE( + network_quality_store.GetById(network_id, &read_network_quality)); + EXPECT_EQ(expected_cached_network_quality.network_quality(), + read_network_quality.network_quality()); + } + } + + { + // When the current network does not have signal strength available, then + // the cached value that corresponds to unknown signal strength should be + // returned. + int32_t signal_strength = INT32_MIN; + nqe::internal::CachedNetworkQuality expected_cached_network_quality = + cached_network_quality_strength_unknown; + nqe::internal::NetworkID network_id(NetworkChangeNotifier::CONNECTION_2G, + "test1", signal_strength); + nqe::internal::CachedNetworkQuality read_network_quality; + EXPECT_TRUE( + network_quality_store.GetById(network_id, &read_network_quality)); + EXPECT_EQ(expected_cached_network_quality.network_quality(), + read_network_quality.network_quality()); + } +} + // Tests if the cache size remains bounded. Also, ensure that the cache is // LRU. TEST(NetworkQualityStoreTest, TestLRUCacheMaximumSize) {
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc index 55748d41..d366ad8 100644 --- a/net/quic/chromium/quic_chromium_client_session.cc +++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -1254,8 +1254,29 @@ if (!ShouldCreateIncomingDynamicStream(id)) { return nullptr; } - // TODO(https://crbug.com/656607): Add proper annotation. - return CreateIncomingReliableStreamImpl(id, NO_TRAFFIC_ANNOTATION_BUG_656607); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("quic_chromium_incoming_session", R"( + semantics { + sender: "Quic Chromium Client Session" + description: + "When a web server needs to push a response to a client, an incoming " + "stream is created to reply the client with pushed message instead " + "of a message from the network." + trigger: + "A request by a server to push a response to the client." + data: "None." + destination: OTHER + destination_other: + "This stream is not used for sending data." + } + policy { + cookies_allowed: NO + setting: "This feature cannot be disabled in settings." + policy_exception_justification: + "Essential for network access." + } + )"); + return CreateIncomingReliableStreamImpl(id, traffic_annotation); } QuicChromiumClientStream*
diff --git a/net/quic/chromium/quic_chromium_packet_writer.cc b/net/quic/chromium/quic_chromium_packet_writer.cc index 6099240..af3b7c0a 100644 --- a/net/quic/chromium/quic_chromium_packet_writer.cc +++ b/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -108,9 +108,34 @@ WriteResult QuicChromiumPacketWriter::WritePacketToSocketImpl() { base::TimeTicks now = base::TimeTicks::Now(); - // TODO(crbug.com/656607:) Add proper annotation. + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("quic_chromium_packet_writer", R"( + semantics { + sender: "QUIC Packet Writer" + description: + "A QUIC packet is written to the wire based on a request from " + "a QUIC stream." + trigger: + "A request from QUIC stream." + data: "Any data sent by the stream." + destination: OTHER + destination_other: "Any destination choosen by the stream." + } + policy { + cookies_allowed: NO + setting: "This feature cannot be disabled in settings." + policy_exception_justification: + "Essential for network access." + } + comments: + "All requests that are received by QUIC streams have network traffic " + "annotation, but the annotation is not passed to the writer function " + "due to technial overheads. Please see QuicChromiumClientSession and " + "QuicChromiumClientStream classes for references." + )"); + int rv = socket_->Write(packet_.get(), packet_->size(), write_callback_, - NO_TRAFFIC_ANNOTATION_BUG_656607); + traffic_annotation); if (MaybeRetryAfterWriteError(rv)) return WriteResult(WRITE_STATUS_BLOCKED, ERR_IO_PENDING);
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc index 210f111..6e816ad9 100644 --- a/net/quic/chromium/quic_stream_factory.cc +++ b/net/quic/chromium/quic_stream_factory.cc
@@ -1353,11 +1353,7 @@ } void QuicStreamFactory::OnSSLConfigChanged() { - // TODO(zhongyi): remove quic_stream_factory from being a - // SSLConfigService::Observer when channel ID is deprecated. - // (See http://crbug.com/809272.) - - MarkAllActiveSessionsGoingAway(); + CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); } void QuicStreamFactory::OnCertDBChanged() {
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 5152fa9..0122d1f6 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -4877,6 +4877,7 @@ MockQuicData socket_data; socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); socket_data.AddWrite(ConstructInitialSettingsPacket()); + socket_data.AddWrite(ConstructClientRstPacket(2, QUIC_RST_ACKNOWLEDGEMENT)); socket_data.AddSocketDataToFactory(socket_factory_.get()); MockQuicData socket_data2; @@ -4893,16 +4894,20 @@ EXPECT_THAT(callback_.WaitForResult(), IsOk()); std::unique_ptr<HttpStream> stream = CreateStream(&request); - EXPECT_TRUE(stream); - QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + HttpRequestInfo request_info; + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, false, DEFAULT_PRIORITY, + net_log_, CompletionCallback())); ssl_config_service_->NotifySSLConfigChange(); + EXPECT_EQ(ERR_CERT_DATABASE_CHANGED, + stream->ReadResponseHeaders(callback_.callback())); EXPECT_FALSE(factory_->require_confirmation()); - EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(host_port_pair_)); // Now attempting to request a stream to the same origin should create // a new session. + QuicStreamRequest request2(factory_.get()); EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_pair_, version_, privacy_mode_, @@ -4911,15 +4916,8 @@ &net_error_details_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); - EXPECT_TRUE(stream2); - - EXPECT_TRUE(HasActiveSession(host_port_pair_)); - EXPECT_NE(session, GetActiveSession(host_port_pair_)); - EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); - - stream2.reset(); - stream.reset(); + stream = CreateStream(&request2); + stream.reset(); // Will reset stream 3. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed());
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc index ef2cb3b2..12f1a44 100644 --- a/net/websockets/websocket_stream_cookie_test.cc +++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <string> +#include <utility> #include "base/callback_forward.h" #include "base/memory/weak_ptr.h" @@ -11,10 +12,13 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" +#include "net/cookies/canonical_cookie.h" +#include "net/cookies/canonical_cookie_test_helpers.h" #include "net/cookies/cookie_store.h" #include "net/socket/socket_test_util.h" #include "net/websockets/websocket_stream_create_test_base.h" #include "net/websockets/websocket_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "url/origin.h" @@ -109,13 +113,13 @@ base::RunLoop().RunUntilIdle(); } - static void GetCookiesHelperFunction(const base::Closure& task, - base::WeakPtr<bool> weak_is_called, - base::WeakPtr<std::string> weak_result, - const std::string& cookies) { + static void GetCookieListHelperFunction(base::OnceClosure task, + base::WeakPtr<bool> weak_is_called, + base::WeakPtr<CookieList> weak_result, + const CookieList& cookie_list) { *weak_is_called = true; - *weak_result = cookies; - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); + *weak_result = cookie_list; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task)); } }; @@ -184,19 +188,19 @@ EXPECT_FALSE(has_failed()); bool is_called = false; - std::string get_cookies_result; + CookieList get_cookie_list_result; base::WeakPtrFactory<bool> weak_is_called(&is_called); - base::WeakPtrFactory<std::string> weak_get_cookies_result( - &get_cookies_result); + base::WeakPtrFactory<CookieList> weak_get_cookie_list_result( + &get_cookie_list_result); base::RunLoop run_loop; - store->GetCookiesWithOptionsAsync( + store->GetCookieListWithOptionsAsync( cookie_url, CookieOptions(), - base::Bind(&GetCookiesHelperFunction, run_loop.QuitClosure(), - weak_is_called.GetWeakPtr(), - weak_get_cookies_result.GetWeakPtr())); + base::BindOnce(&GetCookieListHelperFunction, run_loop.QuitClosure(), + weak_is_called.GetWeakPtr(), + weak_get_cookie_list_result.GetWeakPtr())); run_loop.Run(); EXPECT_TRUE(is_called); - EXPECT_EQ(cookie_line, get_cookies_result); + EXPECT_THAT(get_cookie_list_result, MatchesCookieLine(cookie_line)); } // Test parameters definitions follow...
diff --git a/remoting/ios/app/app_delegate.mm b/remoting/ios/app/app_delegate.mm index 2581fb5..bf79395 100644 --- a/remoting/ios/app/app_delegate.mm +++ b/remoting/ios/app/app_delegate.mm
@@ -8,6 +8,7 @@ #import "remoting/ios/app/app_delegate.h" +#import "remoting/ios/app/app_initializer.h" #import "remoting/ios/app/app_view_controller.h" #import "remoting/ios/app/first_launch_view_presenter.h" #import "remoting/ios/app/help_and_feedback.h" @@ -36,6 +37,7 @@ - (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + [AppInitializer onAppWillFinishLaunching]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; @@ -46,12 +48,14 @@ didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { [self launchRootViewController]; [RemotingTheme applyColorSchemes]; + [AppInitializer onAppDidFinishLaunching]; return YES; } #ifndef NDEBUG // Used by Chromium debug build to authenticate. +// TODO(yuweih): This interface is deprecated in iOS 10 and needs some cleanups. - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url { DCHECK([RemotingService.instance.authentication isKindOfClass:[RemotingOAuthAuthentication class]]);
diff --git a/remoting/ios/app/app_initializer.h b/remoting/ios/app/app_initializer.h index 2f24ede..994d1df 100644 --- a/remoting/ios/app/app_initializer.h +++ b/remoting/ios/app/app_initializer.h
@@ -12,7 +12,12 @@ // it is used. @interface AppInitializer : NSObject -+ (void)initializeApp; +// Called when the launch process has just begun. ++ (void)onAppWillFinishLaunching; + +// Called when the launch process is almost done and the app's window is about +// to present. ++ (void)onAppDidFinishLaunching; @end
diff --git a/remoting/ios/app/app_initializer_chromium.mm b/remoting/ios/app/app_initializer_chromium.mm index 40db542..e50db66 100644 --- a/remoting/ios/app/app_initializer_chromium.mm +++ b/remoting/ios/app/app_initializer_chromium.mm
@@ -15,7 +15,7 @@ @implementation AppInitializer -+ (void)initializeApp { ++ (void)onAppWillFinishLaunching { // |authentication| is nil by default and needs to be injected here. RemotingService.instance.authentication = [[RemotingOAuthAuthentication alloc] init]; @@ -24,4 +24,7 @@ [[RefreshControlProviderChromium alloc] init]; } ++ (void)onAppDidFinishLaunching { +} + @end
diff --git a/remoting/ios/app/main.mm b/remoting/ios/app/main.mm index afd23c7..315326c 100644 --- a/remoting/ios/app/main.mm +++ b/remoting/ios/app/main.mm
@@ -9,7 +9,6 @@ #import <UIKit/UIKit.h> #import "remoting/ios/app/app_delegate.h" -#import "remoting/ios/app/app_initializer.h" #include "base/at_exit.h" #include "base/command_line.h" @@ -43,7 +42,6 @@ ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); @autoreleasepool { - [AppInitializer initializeApp]; return UIApplicationMain( argc, argv, nil, NSStringFromClass([AppDelegate class])); }
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index 0f2eb2b6..2b503c4 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -209,13 +209,7 @@ rtc_config, &constraints, std::move(port_allocator), nullptr, this); } -// TODO(sakal): Remove this ifdef after migration to virtual PeerConnection -// observer is complete. -#ifdef VIRTUAL_PEERCONNECTION_OBSERVER_DESTRUCTOR ~PeerConnectionWrapper() override { -#else - virtual ~PeerConnectionWrapper() { -#endif // PeerConnection creates threads internally, which are stopped when the // connection is closed. Thread.Stop() is a blocking operation. // See crbug.com/660081.
diff --git a/services/device/public/cpp/generic_sensor/OWNERS b/services/device/public/cpp/generic_sensor/OWNERS index bb65116..d5fefd8 100644 --- a/services/device/public/cpp/generic_sensor/OWNERS +++ b/services/device/public/cpp/generic_sensor/OWNERS
@@ -1,2 +1,2 @@ -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS +per-file *_mojom_traits*.*=set noparent +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/services/device/public/cpp/generic_sensor/sensor_struct_traits.cc b/services/device/public/cpp/generic_sensor/sensor_mojom_traits.cc similarity index 90% rename from services/device/public/cpp/generic_sensor/sensor_struct_traits.cc rename to services/device/public/cpp/generic_sensor/sensor_mojom_traits.cc index 39a233e0..bfed47f 100644 --- a/services/device/public/cpp/generic_sensor/sensor_struct_traits.cc +++ b/services/device/public/cpp/generic_sensor/sensor_mojom_traits.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "services/device/public/cpp/generic_sensor/sensor_struct_traits.h" +#include "services/device/public/cpp/generic_sensor/sensor_mojom_traits.h" namespace mojo {
diff --git a/services/device/public/cpp/generic_sensor/sensor_struct_traits.h b/services/device/public/cpp/generic_sensor/sensor_mojom_traits.h similarity index 76% rename from services/device/public/cpp/generic_sensor/sensor_struct_traits.h rename to services/device/public/cpp/generic_sensor/sensor_mojom_traits.h index 641f402..2c2caf3a 100644 --- a/services/device/public/cpp/generic_sensor/sensor_struct_traits.h +++ b/services/device/public/cpp/generic_sensor/sensor_mojom_traits.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_STRUCT_TRAITS_H_ -#define SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_STRUCT_TRAITS_H_ +#ifndef SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_MOJOM_TRAITS_H_ +#define SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_MOJOM_TRAITS_H_ #include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h" #include "services/device/public/mojom/sensor.mojom.h" @@ -23,4 +23,4 @@ } // namespace mojo -#endif // SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_STRUCT_TRAITS_H_ +#endif // SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_MOJOM_TRAITS_H_
diff --git a/services/device/public/mojom/OWNERS b/services/device/public/mojom/OWNERS index 2c44a46..ae29a36aa 100644 --- a/services/device/public/mojom/OWNERS +++ b/services/device/public/mojom/OWNERS
@@ -1,6 +1,6 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS +per-file *_mojom_traits*.*=set noparent +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS per-file *.typemap=set noparent per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/device/public/mojom/sensor.typemap b/services/device/public/mojom/sensor.typemap index 767d2cb..2d65c5e 100644 --- a/services/device/public/mojom/sensor.typemap +++ b/services/device/public/mojom/sensor.typemap
@@ -7,9 +7,9 @@ "//services/device/public/cpp/generic_sensor/platform_sensor_configuration.h", ] traits_headers = - [ "//services/device/public/cpp/generic_sensor/sensor_struct_traits.h" ] + [ "//services/device/public/cpp/generic_sensor/sensor_mojom_traits.h" ] sources = [ - "//services/device/public/cpp/generic_sensor/sensor_struct_traits.cc", + "//services/device/public/cpp/generic_sensor/sensor_mojom_traits.cc", ] type_mappings = [ "device.mojom.SensorConfiguration=device::PlatformSensorConfiguration" ]
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn index cf02653..caa39f59 100644 --- a/services/network/public/cpp/BUILD.gn +++ b/services/network/public/cpp/BUILD.gn
@@ -16,6 +16,8 @@ "cors/cors_url_loader.h", "cors/cors_url_loader_factory.cc", "cors/cors_url_loader_factory.h", + "cors/preflight_cache.cc", + "cors/preflight_cache.h", "cors/preflight_result.cc", "cors/preflight_result.h", "features.cc", @@ -104,6 +106,7 @@ sources = [ "cors/cors_unittest.cc", + "cors/preflight_cache_unittest.cc", "cors/preflight_result_unittest.cc", "mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc", "mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc",
diff --git a/services/network/public/cpp/cors/preflight_cache.cc b/services/network/public/cpp/cors/preflight_cache.cc new file mode 100644 index 0000000..8da391c --- /dev/null +++ b/services/network/public/cpp/cors/preflight_cache.cc
@@ -0,0 +1,68 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/cors/preflight_cache.h" + +#include "url/gurl.h" + +namespace network { + +namespace cors { + +PreflightCache::PreflightCache() = default; +PreflightCache::~PreflightCache() = default; + +void PreflightCache::AppendEntry( + const std::string& origin, + const GURL& url, + std::unique_ptr<PreflightResult> preflight_result) { + DCHECK(preflight_result); + cache_[origin][url.spec()] = std::move(preflight_result); +} + +bool PreflightCache::CheckIfRequestCanSkipPreflight( + const std::string& origin, + const GURL& url, + mojom::FetchCredentialsMode credentials_mode, + const std::string& method, + const net::HttpRequestHeaders& request_headers) { + // Either |origin| or |url| are not in cache. + auto cache_per_origin = cache_.find(origin); + if (cache_per_origin == cache_.end()) + return false; + + auto cache_entry = cache_per_origin->second.find(url.spec()); + if (cache_entry == cache_per_origin->second.end()) + return false; + + // Both |origin| and |url| are in cache. Check if the entry is still valid and + // sufficient to skip CORS-preflight. + if (cache_entry->second->EnsureAllowedRequest(credentials_mode, method, + request_headers)) { + return true; + } + + // The cache entry is either stale or not sufficient. Remove the item from the + // cache. + cache_per_origin->second.erase(url.spec()); + if (cache_per_origin->second.empty()) + cache_.erase(cache_per_origin); + + return false; +} + +size_t PreflightCache::size_for_testing() const { + size_t entries = 0; + // Count the last entries, and per-origin cache entries so that unit tests + // can confirm if a per-origin cache was erased correctly. + // TODO(toyoshim): Split this method to two methods so to count origins and + // entries separately. + for (auto const& cache_per_origin : cache_) + entries += cache_per_origin.second.size() + 1; + return entries; +} + +} // namespace cors + +} // namespace network
diff --git a/services/network/public/cpp/cors/preflight_cache.h b/services/network/public/cpp/cors/preflight_cache.h new file mode 100644 index 0000000..db7d515 --- /dev/null +++ b/services/network/public/cpp/cors/preflight_cache.h
@@ -0,0 +1,63 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_ + +#include <map> +#include <memory> +#include <string> + +#include "base/component_export.h" +#include "base/macros.h" +#include "net/http/http_request_headers.h" +#include "services/network/public/cpp/cors/preflight_result.h" +#include "services/network/public/mojom/fetch_api.mojom-shared.h" + +class GURL; + +namespace network { + +namespace cors { + +// A class to implement CORS-preflight cache that is defined in the fetch spec, +// https://fetch.spec.whatwg.org/#concept-cache. +class COMPONENT_EXPORT(NETWORK_CPP) PreflightCache final { + public: + PreflightCache(); + ~PreflightCache(); + + // Appends new |preflight_result| entry to the cache for a specified |origin| + // and |url|. + void AppendEntry(const std::string& origin, + const GURL& url, + std::unique_ptr<PreflightResult> preflight_result); + + // Consults with cached results, and decides if we can skip CORS-preflight or + // not. + bool CheckIfRequestCanSkipPreflight( + const std::string& origin, + const GURL& url, + mojom::FetchCredentialsMode credentials_mode, + const std::string& method, + const net::HttpRequestHeaders& headers); + + // Returns current number of cached items for testing. + size_t size_for_testing() const; + + private: + // A map for caching. The outer map takes an origin to find a per-origin + // cache map, and the inner map takes an URL to find a cached entry. + std::map<std::string /* origin */, + std::map<std::string /* url */, std::unique_ptr<PreflightResult>>> + cache_; + + DISALLOW_COPY_AND_ASSIGN(PreflightCache); +}; + +} // namespace cors + +} // namespace network + +#endif // SERVICES_NETWORK_PUBLIC_CPP_CORS_PREFLIGHT_CACHE_H_
diff --git a/services/network/public/cpp/cors/preflight_cache_unittest.cc b/services/network/public/cpp/cors/preflight_cache_unittest.cc new file mode 100644 index 0000000..48739c3 --- /dev/null +++ b/services/network/public/cpp/cors/preflight_cache_unittest.cc
@@ -0,0 +1,116 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/cors/preflight_cache.h" + +#include "base/test/simple_test_tick_clock.h" +#include "base/time/time.h" +#include "net/http/http_request_headers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace network { + +namespace cors { + +namespace { + +class PreflightCacheTest : public testing::Test { + public: + PreflightCacheTest() = default; + + protected: + size_t cache_size() const { return cache_.size_for_testing(); } + PreflightCache* cache() { return &cache_; } + + void AppendEntry(const std::string& origin, const GURL& url) { + std::unique_ptr<PreflightResult> result = PreflightResult::Create( + mojom::FetchCredentialsMode::kInclude, std::string("POST"), + base::nullopt, std::string("5"), nullptr); + cache_.AppendEntry(origin, url, std::move(result)); + } + + bool CheckEntryAndRefreshCache(const std::string& origin, const GURL& url) { + return cache_.CheckIfRequestCanSkipPreflight( + origin, url, network::mojom::FetchCredentialsMode::kInclude, "POST", + net::HttpRequestHeaders()); + } + + void Advance(int seconds) { + clock_.Advance(base::TimeDelta::FromSeconds(seconds)); + } + + private: + // testing::Test implementation. + void SetUp() override { PreflightResult::SetTickClockForTesting(&clock_); } + void TearDown() override { PreflightResult::SetTickClockForTesting(nullptr); } + + PreflightCache cache_; + base::SimpleTestTickClock clock_; +}; + +TEST_F(PreflightCacheTest, CacheSize) { + const std::string origin("null"); + const std::string other_origin("http://www.other.com:80"); + const GURL url("http://www.test.com/A"); + const GURL other_url("http://www.test.com/B"); + + // Cache should be empty. + EXPECT_EQ(0u, cache_size()); + + AppendEntry(origin, url); + + // Cache size should be 2 (counting origins and urls separately). + EXPECT_EQ(2u, cache_size()); + + AppendEntry(origin, other_url); + + // Cache size should now be 3 (1 origin, 2 urls). + EXPECT_EQ(3u, cache_size()); + + AppendEntry(other_origin, url); + + // Cache size should now be 4 (4 origin, 3 urls). + EXPECT_EQ(5u, cache_size()); +} + +TEST_F(PreflightCacheTest, CacheTimeout) { + const std::string origin("null"); + const GURL url("http://www.test.com/A"); + const GURL other_url("http://www.test.com/B"); + + // Cache should be empty. + EXPECT_EQ(0u, cache_size()); + + AppendEntry(origin, url); + AppendEntry(origin, other_url); + + // Cache size should be 3 (counting origins and urls separately). + EXPECT_EQ(3u, cache_size()); + + // Cache entry should still be valid. + EXPECT_TRUE(CheckEntryAndRefreshCache(origin, url)); + + // Advance time by ten seconds. + Advance(10); + + // Cache entry should now be expired. + EXPECT_FALSE(CheckEntryAndRefreshCache(origin, url)); + + // Cache size should be 2, with the expired entry removed, but one origin and + // one url still in the cache. + EXPECT_EQ(2u, cache_size()); + + // Cache entry should be expired. + EXPECT_FALSE(CheckEntryAndRefreshCache(origin, other_url)); + + // Cache size should be 0, with the expired entry removed. + EXPECT_EQ(0u, cache_size()); +} + +} // namespace + +} // namespace cors + +} // namespace network
diff --git a/services/ui/public/interfaces/window_manager.mojom b/services/ui/public/interfaces/window_manager.mojom index c43779c0..cba2ae5 100644 --- a/services/ui/public/interfaces/window_manager.mojom +++ b/services/ui/public/interfaces/window_manager.mojom
@@ -153,6 +153,10 @@ // Type: ShowState. const string kShowState_Property = "prop:show-state"; + // The window corner radius in DIPs. Maps to + // aura::client::kWindowCornerRadiusKey. Type: int. + const string kWindowCornerRadius_Property = "prop:window-corner-radius"; + // The window icon; typically 16x16 for titlebars. Type: SkBitmap const string kWindowIcon_Property = "prop:window-icon";
diff --git a/services/ui/ws/display_manager.cc b/services/ui/ws/display_manager.cc index 32884b5d..faed896 100644 --- a/services/ui/ws/display_manager.cc +++ b/services/ui/ws/display_manager.cc
@@ -168,7 +168,7 @@ } } for (size_t i = 0; i < mirrors.size(); ++i) { - NOTIMPLEMENTED() << "TODO(crbug.com/764472): Mus mirroring/unified mode."; + NOTIMPLEMENTED() << "TODO(crbug.com/806318): Mus+Viz mirroring/unified"; Display* ws_mirror = GetDisplayById(mirrors[i].id()); const auto& metrics = viewport_metrics[displays.size() + i]; if (!ws_mirror) {
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc index c47d563..1ac78557 100644 --- a/services/ui/ws/window_tree.cc +++ b/services/ui/ws/window_tree.cc
@@ -345,7 +345,7 @@ } if (!mirrors.empty()) - NOTIMPLEMENTED() << "TODO(crbug.com/764472): Mus unified mode support."; + NOTIMPLEMENTED() << "TODO(crbug.com/806318): Mus+Viz mirroring/unified"; DCHECK(display); WindowManagerDisplayRoot* display_root =
diff --git a/storage/browser/blob/blob_builder_from_stream.cc b/storage/browser/blob/blob_builder_from_stream.cc index 0fa1041..4f98cc77 100644 --- a/storage/browser/blob/blob_builder_from_stream.cc +++ b/storage/browser/blob/blob_builder_from_stream.cc
@@ -65,8 +65,11 @@ } virtual ~DataPipeConsumerHelper() = default; - virtual void Populate(base::span<const char> data, uint64_t offset) = 0; + // Return false if population fails. + virtual bool Populate(base::span<const char> data, + uint64_t bytes_previously_written) = 0; virtual void InvokeDone(mojo::ScopedDataPipeConsumerHandle pipe, + bool success, uint64_t bytes_written) = 0; private: @@ -88,15 +91,19 @@ } DCHECK_EQ(MOJO_RESULT_OK, result); size = std::min<uint64_t>(size, max_bytes_to_read_ - current_offset_); - Populate(base::make_span(static_cast<const char*>(data), size), - current_offset_); + if (!Populate(base::make_span(static_cast<const char*>(data), size), + current_offset_)) { + InvokeDone(mojo::ScopedDataPipeConsumerHandle(), false, + current_offset_); + delete this; + } current_offset_ += size; result = pipe_->EndReadData(size); DCHECK_EQ(MOJO_RESULT_OK, result); } // Either the pipe closed, or we filled the entire item. - InvokeDone(std::move(pipe_), current_offset_); + InvokeDone(std::move(pipe_), true, current_offset_); delete this; } @@ -115,10 +122,24 @@ : public DataPipeConsumerHelper { public: using DoneCallback = - base::OnceCallback<void(uint64_t bytes_written, + base::OnceCallback<void(bool success, + uint64_t bytes_written, mojo::ScopedDataPipeConsumerHandle pipe, const base::Time& modification_time)>; + static void CreateAndAppend(mojo::ScopedDataPipeConsumerHandle pipe, + base::FilePath file_path, + uint64_t max_file_size, + DoneCallback callback) { + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}) + ->PostTask( + FROM_HERE, + base::BindOnce( + &WritePipeToFileHelper::CreateAndAppendOnFileSequence, + std::move(pipe), std::move(file_path), max_file_size, + base::SequencedTaskRunnerHandle::Get(), std::move(callback))); + } + static void CreateAndStart(mojo::ScopedDataPipeConsumerHandle pipe, base::File file, uint64_t max_file_size, @@ -133,6 +154,17 @@ } private: + static void CreateAndAppendOnFileSequence( + mojo::ScopedDataPipeConsumerHandle pipe, + base::FilePath file_path, + uint64_t max_file_size, + scoped_refptr<base::TaskRunner> reply_runner, + DoneCallback callback) { + base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_APPEND); + new WritePipeToFileHelper(std::move(pipe), std::move(file), max_file_size, + std::move(reply_runner), std::move(callback)); + } + static void CreateAndStartOnFileSequence( mojo::ScopedDataPipeConsumerHandle pipe, base::File file, @@ -153,19 +185,23 @@ reply_runner_(std::move(reply_runner)), callback_(std::move(callback)) {} - void Populate(base::span<const char> data, uint64_t offset) override { - file_.Write(offset, data.data(), data.size()); + bool Populate(base::span<const char> data, + uint64_t bytes_previously_written) override { + return file_.WriteAtCurrentPos(data.data(), data.size()) >= 0; } void InvokeDone(mojo::ScopedDataPipeConsumerHandle pipe, + bool success, uint64_t bytes_written) override { base::Time last_modified; - base::File::Info info; - if (file_.Flush() && file_.GetInfo(&info)) - last_modified = info.last_modified; - reply_runner_->PostTask(FROM_HERE, - base::BindOnce(std::move(callback_), bytes_written, - std::move(pipe), last_modified)); + if (success) { + base::File::Info info; + if (file_.Flush() && file_.GetInfo(&info)) + last_modified = info.last_modified; + } + reply_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback_), success, bytes_written, + std::move(pipe), last_modified)); } base::File file_; @@ -197,15 +233,21 @@ item_(std::move(item)), callback_(std::move(callback)) {} - void Populate(base::span<const char> data, uint64_t offset) override { + bool Populate(base::span<const char> data, + uint64_t bytes_previously_written) override { if (item_->type() == BlobDataItem::Type::kBytesDescription) item_->AllocateBytes(); - std::memcpy(item_->mutable_bytes().subspan(offset, data.length()).data(), + std::memcpy(item_->mutable_bytes() + .subspan(bytes_previously_written, data.length()) + .data(), data.data(), data.length()); + return true; } void InvokeDone(mojo::ScopedDataPipeConsumerHandle pipe, + bool success, uint64_t bytes_written) override { + DCHECK(success); std::move(callback_).Run(bytes_written, std::move(pipe)); } @@ -361,15 +403,35 @@ if (!length_hint) length_hint = kFileBlockSize; - // TODO(mek): Extend existing file until max_page_file_size is reached, rather - // then creating multiple min_page_file_size files. - if (context_->memory_controller().GetAvailableFileSpaceForBlobs() < length_hint) { OnError(); return; } + // If the previous item was also a file, and the file isn't at its maximum + // size yet, extend the previous file rather than creating a new one. + if (!items_.empty() && + items_.back()->item()->type() == BlobDataItem::Type::kFile && + items_.back()->item()->length() < kMaxFileSize) { + auto item = items_.back()->item(); + uint64_t old_file_size = item->length(); + scoped_refptr<ShareableFileReference> file_reference = + static_cast<ShareableFileReference*>(item->data_handle()); + DCHECK(file_reference); + auto file_size_delta = std::min(kMaxFileSize - old_file_size, length_hint); + context_->mutable_memory_controller()->GrowFileAllocation( + file_reference.get(), file_size_delta); + item->GrowFile(old_file_size + file_size_delta); + base::FilePath path = file_reference->path(); + WritePipeToFileHelper::CreateAndAppend( + std::move(pipe), path, file_size_delta, + base::BindOnce(&BlobBuilderFromStream::DidWriteToExtendedFile, + weak_factory_.GetWeakPtr(), std::move(file_reference), + old_file_size)); + return; + } + std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items; while (length_hint > 0) { const auto file_size = std::min(kMaxFileSize, length_hint); @@ -411,10 +473,11 @@ std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items, std::vector<BlobMemoryController::FileCreationInfo> info, size_t populated_item_index, + bool success, uint64_t bytes_written, mojo::ScopedDataPipeConsumerHandle pipe, const base::Time& modification_time) { - if (!context_ || !callback_) { + if (!success || !context_ || !callback_) { OnError(); return; } @@ -456,6 +519,42 @@ } } +void BlobBuilderFromStream::DidWriteToExtendedFile( + scoped_refptr<ShareableFileReference> file_reference, + uint64_t old_file_size, + bool success, + uint64_t bytes_written, + mojo::ScopedDataPipeConsumerHandle pipe, + const base::Time& modification_time) { + if (!success || !context_ || !callback_) { + OnError(); + return; + } + DCHECK(!items_.empty()); + auto item = items_.back()->item(); + DCHECK_EQ(item->type(), BlobDataItem::Type::kFile); + DCHECK_EQ(item->data_handle(), file_reference.get()); + + item->SetFileModificationTime(modification_time); + current_total_size_ += bytes_written; + + if (pipe.is_valid()) { + DCHECK_EQ(item->length(), old_file_size + bytes_written); + // Once we start writing to file, we keep writing to file. + RunCallbackWhenDataPipeReady( + std::move(pipe), + base::BindOnce(&BlobBuilderFromStream::AllocateMoreFileSpace, + weak_factory_.GetWeakPtr(), 0)); + } else { + // Pipe has closed, so we must be done. + DCHECK_LE(old_file_size + bytes_written, item->length()); + context_->mutable_memory_controller()->ShrinkFileAllocation( + file_reference.get(), item->length(), old_file_size + bytes_written); + item->ShrinkFile(old_file_size + bytes_written); + OnSuccess(); + } +} + void BlobBuilderFromStream::OnError() { if (pending_quota_task_) pending_quota_task_->Cancel();
diff --git a/storage/browser/blob/blob_builder_from_stream.h b/storage/browser/blob/blob_builder_from_stream.h index a9366e4..63749a04 100644 --- a/storage/browser/blob/blob_builder_from_stream.h +++ b/storage/browser/blob/blob_builder_from_stream.h
@@ -86,6 +86,14 @@ std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items, std::vector<BlobMemoryController::FileCreationInfo> info, size_t populated_item_index, + bool success, + uint64_t bytes_written, + mojo::ScopedDataPipeConsumerHandle pipe, + const base::Time& modification_time); + void DidWriteToExtendedFile( + scoped_refptr<ShareableFileReference> file_reference, + uint64_t old_file_size, + bool success, uint64_t bytes_written, mojo::ScopedDataPipeConsumerHandle pipe, const base::Time& modification_time);
diff --git a/storage/browser/blob/blob_builder_from_stream_unittest.cc b/storage/browser/blob/blob_builder_from_stream_unittest.cc index 105b0c8..5bbec25 100644 --- a/storage/browser/blob/blob_builder_from_stream_unittest.cc +++ b/storage/browser/blob/blob_builder_from_stream_unittest.cc
@@ -4,6 +4,7 @@ #include "storage/browser/blob/blob_builder_from_stream.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/rand_util.h" #include "base/run_loop.h" @@ -12,6 +13,7 @@ #include "base/test/bind_test_util.h" #include "base/test/scoped_task_environment.h" #include "mojo/common/data_pipe_utils.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_storage_context.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,6 +25,7 @@ constexpr size_t kTestBlobStorageMaxBytesDataItemSize = 13; constexpr size_t kTestBlobStorageMaxBlobMemorySize = 500; constexpr uint64_t kTestBlobStorageMinFileSizeBytes = 32; +constexpr uint64_t kTestBlobStorageMaxFileSizeBytes = 100; constexpr uint64_t kTestBlobStorageMaxDiskSpace = 1000; enum class LengthHintTestType { @@ -46,6 +49,7 @@ limits_.max_bytes_data_item_size = kTestBlobStorageMaxBytesDataItemSize; limits_.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize; limits_.min_page_file_size = kTestBlobStorageMinFileSizeBytes; + limits_.max_file_size = kTestBlobStorageMaxFileSizeBytes; limits_.desired_max_disk_space = kTestBlobStorageMaxDiskSpace; limits_.effective_max_disk_space = kTestBlobStorageMaxDiskSpace; context_->set_limits_for_testing(limits_); @@ -109,6 +113,51 @@ return result; } + void VerifyBlobContents(base::span<const char> in_memory_data, + base::span<const char> on_disk_data, + const BlobDataSnapshot& blob_data) { + size_t next_memory_offset = 0; + size_t next_file_offset = 0; + for (const auto& item : blob_data.items()) { + if (item->type() == BlobDataItem::Type::kBytes) { + EXPECT_EQ(0u, next_file_offset) + << "Bytes item after file items is invalid"; + + EXPECT_LE(item->length(), kTestBlobStorageMaxBlobMemorySize); + ASSERT_LE(next_memory_offset + item->length(), in_memory_data.size()); + + EXPECT_EQ(in_memory_data.subspan(next_memory_offset, item->length()), + item->bytes()); + + next_memory_offset += item->length(); + } else if (item->type() == BlobDataItem::Type::kFile) { + EXPECT_EQ(next_memory_offset, in_memory_data.size()) + << "File item before all in memory data was found"; + + EXPECT_LE(item->length(), kTestBlobStorageMaxFileSizeBytes); + ASSERT_LE(next_file_offset + item->length(), on_disk_data.size()); + + std::string file_contents; + EXPECT_TRUE(base::ReadFileToString(item->path(), &file_contents)); + EXPECT_EQ(item->length(), file_contents.size()); + EXPECT_EQ(on_disk_data.subspan(next_file_offset, item->length()), + base::make_span(file_contents)); + + next_file_offset += item->length(); + if (next_file_offset < on_disk_data.size()) { + EXPECT_EQ(kTestBlobStorageMaxFileSizeBytes, item->length()) + << "All but the last file should be max sized"; + } + } else { + ADD_FAILURE() << "Invalid blob item type: " + << static_cast<int>(item->type()); + } + } + + EXPECT_EQ(next_memory_offset, in_memory_data.size()); + EXPECT_EQ(next_file_offset, on_disk_data.size()); + } + protected: const std::string kContentType = "content/type"; const std::string kContentDisposition = "disposition"; @@ -151,6 +200,10 @@ // Verify memory usage. EXPECT_EQ(0u, context_->memory_controller().memory_usage()); EXPECT_EQ(0u, context_->memory_controller().disk_usage()); + + // Verify blob contents. + VerifyBlobContents(base::span<const char>(), base::span<const char>(), + *result->CreateSnapshot()); } TEST_P(BlobBuilderFromStreamTest, SmallStream) { @@ -166,6 +219,10 @@ // Verify memory usage. EXPECT_EQ(kData.size(), context_->memory_controller().memory_usage()); EXPECT_EQ(0u, context_->memory_controller().disk_usage()); + + // Verify blob contents. + VerifyBlobContents(kData, base::span<const char>(), + *result->CreateSnapshot()); } TEST_P(BlobBuilderFromStreamTest, MediumStream) { @@ -188,6 +245,18 @@ EXPECT_EQ(0u, context_->memory_controller().memory_usage()); EXPECT_EQ(kData.size(), context_->memory_controller().disk_usage()); } + + // Verify blob contents. + if (GetParam() == LengthHintTestType::kUnknownSize) { + VerifyBlobContents(base::make_span(kData).subspan( + 0, 2 * kTestBlobStorageMaxBytesDataItemSize), + base::make_span(kData).subspan( + 2 * kTestBlobStorageMaxBytesDataItemSize), + *result->CreateSnapshot()); + } else { + VerifyBlobContents(base::span<const char>(), kData, + *result->CreateSnapshot()); + } } TEST_P(BlobBuilderFromStreamTest, LargeStream) { @@ -218,6 +287,18 @@ EXPECT_EQ(0u, context_->memory_controller().memory_usage()); EXPECT_EQ(kData.size(), context_->memory_controller().disk_usage()); } + + // Verify blob contents. + if (GetParam() == LengthHintTestType::kUnknownSize) { + VerifyBlobContents(base::make_span(kData).subspan( + 0, 2 * kTestBlobStorageMaxBytesDataItemSize), + base::make_span(kData).subspan( + 2 * kTestBlobStorageMaxBytesDataItemSize), + *result->CreateSnapshot()); + } else { + VerifyBlobContents(base::span<const char>(), kData, + *result->CreateSnapshot()); + } } TEST_P(BlobBuilderFromStreamTest, TooLargeForQuota) {
diff --git a/storage/browser/blob/blob_data_item.cc b/storage/browser/blob/blob_data_item.cc index b04fd17..67b02d6 100644 --- a/storage/browser/blob/blob_data_item.cc +++ b/storage/browser/blob/blob_data_item.cc
@@ -157,6 +157,13 @@ void BlobDataItem::ShrinkFile(uint64_t new_length) { DCHECK_EQ(type_, Type::kFile); + DCHECK_LE(new_length, length_); + length_ = new_length; +} + +void BlobDataItem::GrowFile(uint64_t new_length) { + DCHECK_EQ(type_, Type::kFile); + DCHECK_GE(new_length, length_); length_ = new_length; }
diff --git a/storage/browser/blob/blob_data_item.h b/storage/browser/blob/blob_data_item.h index e60c2ad..d976e59 100644 --- a/storage/browser/blob/blob_data_item.h +++ b/storage/browser/blob/blob_data_item.h
@@ -127,6 +127,12 @@ return disk_cache_side_stream_index_; } + DataHandle* data_handle() const { + DCHECK(type_ == Type::kFile || type_ == Type::kDiskCacheEntry) + << static_cast<int>(type_); + return data_handle_.get(); + } + // Returns true if this item was created by CreateFutureFile. bool IsFutureFileItem() const; // Returns |file_id| given to CreateFutureFile. @@ -155,6 +161,11 @@ base::Time expected_modification_time, scoped_refptr<DataHandle> data_handle); void ShrinkFile(uint64_t new_length); + void GrowFile(uint64_t new_length); + void SetFileModificationTime(base::Time time) { + DCHECK_EQ(type_, Type::kFile); + expected_modification_time_ = time; + } static void SetFileModificationTimes( std::vector<scoped_refptr<BlobDataItem>> items,
diff --git a/storage/browser/blob/blob_memory_controller.cc b/storage/browser/blob/blob_memory_controller.cc index 61baa31..4dd8fbe 100644 --- a/storage/browser/blob/blob_memory_controller.cc +++ b/storage/browser/blob/blob_memory_controller.cc
@@ -667,6 +667,16 @@ weak_factory_.GetWeakPtr(), old_length - new_length)); } +void BlobMemoryController::GrowFileAllocation( + ShareableFileReference* file_reference, + uint64_t delta) { + DCHECK_LE(delta, GetAvailableFileSpaceForBlobs()); + disk_used_ += delta; + file_reference->AddFinalReleaseCallback( + base::BindRepeating(&BlobMemoryController::OnBlobFileDelete, + weak_factory_.GetWeakPtr(), delta)); +} + void BlobMemoryController::NotifyMemoryItemsUsed( const std::vector<scoped_refptr<ShareableBlobDataItem>>& items) { for (const auto& item : items) {
diff --git a/storage/browser/blob/blob_memory_controller.h b/storage/browser/blob/blob_memory_controller.h index 964154f..f13bcda 100644 --- a/storage/browser/blob/blob_memory_controller.h +++ b/storage/browser/blob/blob_memory_controller.h
@@ -178,6 +178,8 @@ void ShrinkFileAllocation(ShareableFileReference* file_reference, uint64_t old_length, uint64_t new_length); + void GrowFileAllocation(ShareableFileReference* file_reference, + uint64_t delta); using DiskSpaceFuncPtr = int64_t (*)(const base::FilePath&);
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc index b8f8212..783b371d 100644 --- a/storage/browser/quota/quota_settings.cc +++ b/storage/browser/quota/quota_settings.cc
@@ -56,22 +56,18 @@ // total to take os_accomodation into account. const double kTemporaryPoolSizeRatio = 1.0 / 3.0; // 33% - // The fraction of the device's storage the browser attempts to + // The amount of the device's storage the browser attempts to // keep free. If there is less than this amount of storage free // on the device, Chrome will grant 0 quota to origins. - // Examples: - // 32GB device: 1% is 320MB - // 200GB device: 1% is 2GB - // 1TB device: 1% is 10GB - const double kShouldRemainAvailableRatio = 0.01; // 1% + // + // Prior to M66, this was 10% of total storage instead of a fixed value. + const int64_t kShouldRemainAvailable = 2048 * kMBytes; // 2GB - // The fraction of the device's storage the browser attempts to + // The amount of the device's storage the browser attempts to // keep free at all costs. Data will be aggressively evicted. - // Examples: - // 32GB device: 0.25% is 80MB - // 200GB device: 0.25% is 500MB - // 1TB device: 0.25% is 2.5GB - const double kMustRemainAvailableRatio = 0.0025; // 0.25% + // + // Prior to M66, this was 1% of total storage instead of a fixed value. + const int64_t kMustRemainAvailable = 1024 * kMBytes; // 1GB // Determines the portion of the temp pool that can be // utilized by a single host (ie. 5 for 20%). @@ -116,8 +112,8 @@ int64_t pool_size = adjusted_total * kTemporaryPoolSizeRatio; settings.pool_size = pool_size; - settings.should_remain_available = total * kShouldRemainAvailableRatio; - settings.must_remain_available = total * kMustRemainAvailableRatio; + settings.should_remain_available = kShouldRemainAvailable; + settings.must_remain_available = kMustRemainAvailable; settings.per_host_quota = pool_size / kPerHostTemporaryPortion; settings.session_only_per_host_quota = std::min( RandomizeByPercent(kMaxSessionOnlyHostQuota, kRandomizedPercentage),
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 8322adb..a11b0e7 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -729,6 +729,12 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "net_unittests" }, { @@ -906,6 +912,12 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "net_unittests" }, { @@ -1543,6 +1555,33 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "LMY47W", + "device_type": "sprout" + } + ], + "expiration": 14400, + "hard_timeout": 300 + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -2767,6 +2806,50 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "NRD91N", + "device_type": "bullhead" + } + ], + "expiration": 10800, + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -3411,6 +3494,12 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "net_unittests" }, { @@ -3599,6 +3688,12 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "net_unittests" }, { @@ -4432,7 +4527,8 @@ { "device_type": "coho" } - ] + ], + "hard_timeout": 300 }, "test": "mojo_unittests" }, @@ -5325,7 +5421,7 @@ "device_type": "gce_x86" } ], - "hard_timeout": 120 + "hard_timeout": 300 }, "test": "mojo_unittests" },
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index c61d0f00..590c0c89 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -1648,7 +1648,7 @@ "device_type": "hammerhead" } ], - "hard_timeout": 180, + "hard_timeout": 300, "output_links": [ { "link": [ @@ -3244,7 +3244,7 @@ "device_type": "hammerhead" } ], - "hard_timeout": 180, + "hard_timeout": 300, "output_links": [ { "link": [ @@ -4681,6 +4681,50 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84Z", + "device_type": "flo" + } + ], + "expiration": 10800, + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -6189,6 +6233,50 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY48I", + "device_type": "hammerhead" + } + ], + "expiration": 10800, + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -7652,6 +7740,50 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY49B", + "device_type": "flo" + } + ], + "expiration": 10800, + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -9181,6 +9313,49 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead" + } + ], + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -12332,6 +12507,50 @@ "--bucket", "chromium-result-details", "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MRA58Z", + "device_type": "flo" + } + ], + "expiration": 10800, + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "net_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 26753043..0566fbe 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -5747,6 +5747,12 @@ }, { "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_unittests" + }, + { + "swarming": { "can_use_on_swarming_builders": true, "shards": 4 },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index d29d6173..adabdbe 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -4029,31 +4029,6 @@ }, "test": "ui_base_unittests" } - ], - "isolated_scripts": [ - { - "args": [ - "--platform", - "fuchsia" - ], - "isolate_name": "webkit_layout_tests_exparchive", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results" - }, - "name": "webkit_layout_tests", - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "kvm": "1" - } - ] - } - } ] }, "Fuchsia (dbg)": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 997cf64..c4ca742 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -158,6 +158,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, { @@ -367,6 +373,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "net_unittests" }, {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index ea283d0..2d4bdcc6 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -2724,6 +2724,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "native_theme_unittests" }, {
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter index bb83ebd..c16d9c5 100644 --- a/testing/buildbot/filters/mash.browser_tests.filter +++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -259,9 +259,8 @@ -PowerPolicyLoginScreenBrowserTest.SetDevicePolicy -EnterpriseEnrollmentTest.TestActiveDirectoryEnrollment_Success -# Access aura window shadow layer. http://crbug.com/811859 --OmniboxPopupContentsViewTest.PopupAlignment/Rounded --RoundedOmniboxPopupContentsViewTest.* +# Needs EventGenerator to work across window tree hosts. crbug.com/814675 +-RoundedOmniboxPopupContentsViewTest.ClickOmnibox* # HostedAppMenu needs porting to BrowserNonClientFrameViewMus crbug.com/813666 -HostedAppPWAOnlyTest.AppInfoOpensPageInfo*
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 062dbcd..85f70d8 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2347,53 +2347,6 @@ }, }, }, - 'mojo_unittests': { - 'remove_from': [ - # On chromium.android, unclear why these aren't run on all bots. - 'KitKat Tablet Tester', - 'Lollipop Phone Tester', - 'Lollipop Tablet Tester', - 'Marshmallow 64 bit Tester', - 'Marshmallow Tablet Tester', - 'Nougat Phone Tester', - # chromium.android.fyi - 'Jelly Bean Tester', - 'Lollipop Consumer Tester', - 'Lollipop Low-end Tester', - 'Unswarmed N5 Tests Dummy Builder', - 'Unswarmed N5X Tests Dummy Builder', - # chromium.chromiumos - 'Linux ChromiumOS Tests (dbg)(1)', - 'linux-chromeos-dbg', - 'linux-chromeos-rel', - # chromium.clang - 'ToTLinuxASan', - # chromium.linux - 'Cast Audio Linux', - 'Cast Linux', - # chromium.memory - 'Linux TSan Tests', - ], - 'modifications': { - # chromium.android - 'Marshmallow Phone Tester (rel)': { - 'swarming': { - 'hard_timeout': 300, - }, - }, - # chromium.android.fyi - 'x64 Device Tester': { - 'swarming': { - 'hard_timeout': 0, - }, - }, - 'x86 Cloud Tester': { - 'swarming': { - 'hard_timeout': 120, - }, - }, - }, - }, 'mojo_test_apk': { 'remove_from': [ # On chromium.android, unclear why these aren't run on all bots. @@ -2574,20 +2527,20 @@ 'Win7 (32) Tests', 'Win7 Tests (1)', 'Win7 Tests (dbg)(1)', - # chromium.clang, the following bots run on Windows 7, where the unit test doesn't run. - 'CrWinAsan', - 'CrWinAsan(dll)', - 'CrWinAsanCov', - 'CrWinClang', - 'CrWinClang(dbg)', - 'CrWinClang(shared)', - 'CrWinClang64', - 'CrWinClang64(dbg)', - 'CrWinClang64(dll)', - 'CrWinClangLLD', - 'CrWinClangLLD64', - 'CrWinClngLLD64dbg', - 'CrWinClngLLDdbg', + # chromium.clang, the following bots run on Windows 7, where the unit test doesn't run. + 'CrWinAsan', + 'CrWinAsan(dll)', + 'CrWinAsanCov', + 'CrWinClang', + 'CrWinClang(dbg)', + 'CrWinClang(shared)', + 'CrWinClang64', + 'CrWinClang64(dbg)', + 'CrWinClang64(dll)', + 'CrWinClangLLD', + 'CrWinClangLLD64', + 'CrWinClngLLD64dbg', + 'CrWinClngLLDdbg', 'ToTWin', 'ToTWin(dbg)', 'ToTWin(dll)', @@ -2596,11 +2549,11 @@ 'ToTWin64(dll)', 'ToTWinCFI', 'ToTWinCFI64', - 'ToTWinThinLTO64', - # chromium.fyi - 'CrWinAsan tester', - 'CrWinAsan(dll) tester', - 'CrWinAsanCov tester', + 'ToTWinThinLTO64', + # chromium.fyi + 'CrWinAsan tester', + 'CrWinAsan(dll) tester', + 'CrWinAsanCov tester', 'Out of Process Profiling Windows', ], }, @@ -3684,11 +3637,6 @@ 'shards': 6, }, }, - 'Fuchsia': { - 'args': [ - '--platform', 'fuchsia', - ], - }, 'WebKit Linux layout_ng Dummy Builder': { 'args': [ '--additional-driver-flag=--enable-blink-features=LayoutNG',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 7e71c89..e1202c7bb 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1355,7 +1355,7 @@ }, 'mojo_unittests': { 'android_swarming': { - 'hard_timeout': 180, + 'hard_timeout': 300, }, }, },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e387383..7206b37 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1003,7 +1003,6 @@ }, 'test_suites': { 'gtest_tests': 'fuchsia_gtests', - 'isolated_scripts': 'webkit_layout_tests_isolated_scripts', }, }, 'Fuchsia (dbg)': {
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index f345579..896f0436 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -837,8 +837,7 @@ crbug.com/591099 editing/selection/paragraph-granularity.html [ Failure ] crbug.com/591099 editing/selection/programmatic-selection-on-mac-is-directionless.html [ Timeout ] crbug.com/591099 editing/selection/range-between-block-and-inline.html [ Failure ] -crbug.com/591099 editing/selection/select-across-readonly-input-2.html [ Failure ] -crbug.com/591099 editing/selection/select-across-readonly-input-3.html [ Failure ] +crbug.com/811502 editing/selection/select-across-readonly-input-1.html [ Crash ] crbug.com/591099 editing/selection/select-bidi-run.html [ Failure ] crbug.com/591099 editing/selection/select-box.html [ Failure ] crbug.com/591099 editing/selection/select-element-paragraph-boundary.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 297a38f..a3df6fc7 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1289,12 +1289,12 @@ crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001b.xhtml [ Failure ] crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-003.xhtml [ Failure ] crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-005.xhtml [ Failure ] -crbug.com/467127 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-010.html [ Failure Pass ] -crbug.com/467127 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Failure Pass ] -crbug.com/467127 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Failure Pass ] -crbug.com/467127 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-013.html [ Failure Pass ] -crbug.com/467127 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-014.html [ Failure Pass ] -crbug.com/467127 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-015.html [ Failure Pass ] +crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-010.html [ Failure Pass ] +crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Failure Pass ] +crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Failure Pass ] +crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-013.html [ Failure Pass ] +crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-014.html [ Failure Pass ] +crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-015.html [ Failure Pass ] crbug.com/654999 [ Win Linux ] fast/forms/color/color-suggestion-picker-appearance-zoom200.html [ Pass Failure ] crbug.com/660185 [ Mac ] fast/forms/datalist/input-appearance-range-with-transform.html [ Pass Failure ] @@ -1479,8 +1479,8 @@ crbug.com/600248 external/wpt/web-animations/interfaces/Animation/oncancel.html [ Pass Failure ] crbug.com/771977 external/wpt/web-animations/interfaces/Animation/onfinish.html [ Failure ] crbug.com/772048 crbug.com/772060 external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html [ Timeout ] -crbug.com/816534 external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html [ Pass Crash ] -crbug.com/816534 external/wpt/web-animations/animation-model/animation-types/addition-per-property.html [ Pass Crash ] +crbug.com/816534 external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html [ Pass Crash Failure ] +crbug.com/816534 external/wpt/web-animations/animation-model/animation-types/addition-per-property.html [ Pass Crash Failure ] crbug.com/771722 external/wpt/web-animations/timing-model/animations/the-current-time-of-an-animation.html [ Failure ] crbug.com/771722 crbug.com/771751 crbug.com/772060 external/wpt/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html [ Failure ] @@ -1714,28 +1714,28 @@ crbug.com/626703 [ Linux Win7 ] external/wpt/css/css-text/word-break/word-break-break-all-007.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-normal-tdd-000.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/textarea-pre-wrap-008.html [ Failure ] -crbug.com/626703 [ Win7 ] external/wpt/css/css-text/white-space/textarea-pre-wrap-014.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/textarea-pre-wrap-014.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/hanging-punctuation/hanging-punctuation-force-end-001.xht [ Skip ] crbug.com/626703 external/wpt/css/css-text/line-breaking/line-breaking-ic-002.html [ Failure ] -crbug.com/626703 [ Win10 ] external/wpt/css/css-text/text-align/text-align-end-003.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-end-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-006.html [ Failure ] -crbug.com/626703 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-013.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/pre-wrap-013.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/css-text/word-break/word-break-normal-bo-000.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-002.html [ Failure ] -crbug.com/626703 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-011.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/pre-wrap-011.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/textarea-pre-wrap-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/line-breaking/line-breaking-009.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/line-breaking/line-breaking-011.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/hanging-punctuation/hanging-punctuation-last-001.xht [ Skip ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-005.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/textarea-pre-wrap-005.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-tailoring-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-003.html [ Failure ] -crbug.com/626703 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-004.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/pre-wrap-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/white-space-collapsing-preserve-breaks-001.xht [ Failure ] crbug.com/626703 [ Linux Mac10.12 Retina Win ] external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-028.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/pre-wrap-006.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/pre-wrap-006.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-capitalize-028.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-004.xht [ Skip ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-009.xht [ Skip ] @@ -1744,13 +1744,13 @@ crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-normal-km-000.html [ Failure ] crbug.com/626703 [ Linux Win ] external/wpt/css/css-text/text-transform/text-transform-upperlower-016.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/pre-wrap-010.html [ Failure ] -crbug.com/626703 [ Win10 ] external/wpt/css/css-text/text-align/text-align-end-016.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-end-016.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-fullwidth-001.xht [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-normal-my-000.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/css/css-text/text-justify/text-justify-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-029.html [ Failure ] -crbug.com/626703 [ Win10 ] external/wpt/css/css-text/text-align/text-align-start-004.html [ Failure ] +crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-start-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-006.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/hanging-punctuation/hanging-punctuation-allow-end-001.xht [ Skip ] crbug.com/626703 external/wpt/css/css-text/white-space/white-space-collapsing-discard-001.xht [ Failure ] @@ -2050,7 +2050,7 @@ crbug.com/626703 external/wpt/wasm/wasm_local_iframe_test.html [ Failure ] crbug.com/626703 external/wpt/wasm/wasm_serialization_tests.html [ Failure ] crbug.com/626703 external/wpt/wasm/wasm_service_worker_test.https.html [ Failure ] -crbug.com/816534 external/wpt/web-animations/animation-model/animation-types/accumulation-per-property.html [ Pass Crash ] +crbug.com/816534 external/wpt/web-animations/animation-model/animation-types/accumulation-per-property.html [ Pass Crash Failure ] crbug.com/626703 external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html [ Timeout ] crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-rollback.html [ Timeout ] crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-setRemoteDescription.html [ Timeout ] @@ -3412,7 +3412,6 @@ crbug.com/417782 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Timeout ] crbug.com/417782 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Timeout ] crbug.com/417782 http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Failure ] -crbug.com/417782 http/tests/misc/acid3.html [ Failure ] crbug.com/417782 inspector-protocol/css/css-get-background-colors.js [ Failure ] crbug.com/417782 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ] crbug.com/417782 paint/invalidation/window-resize/window-resize-vertical-writing-mode.html [ Crash ] @@ -3489,26 +3488,50 @@ # Sheriff 2018-02-26 crbug.com/816475 [ Win7 ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-end-007.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-end-008.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-end-016.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-end-017.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-justify-001.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-justify-002.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-justify-003.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-start-015.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-start-016.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/text-align/text-align-start-017.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-001.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-003.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-007.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-009.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-012.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/pre-wrap-014.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/textarea-pre-wrap-003.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/textarea-pre-wrap-004.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/textarea-pre-wrap-006.html [ Failure Pass ] -crbug.com/816868 [ Win7 ] external/wpt/css/css-text/white-space/textarea-pre-wrap-011.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-001.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-002.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-006.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-007.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-008.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-009.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-010.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-014.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-015.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-end-017.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-justify-001.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-justify-002.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-justify-003.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-justify-005.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-justify-006.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-001.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-002.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-003.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-005.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-006.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-007.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-008.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-009.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-010.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-014.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-015.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-016.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/text-align/text-align-start-017.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-001.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-003.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-005.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-007.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-009.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-012.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/pre-wrap-014.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-001.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-003.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-004.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-006.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-007.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-009.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-011.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html [ Failure Pass ] +crbug.com/816868 [ Mac Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html [ Failure Pass ] crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ] crbug.com/816766 [ Mac ] fast/dom/Window/window-focus-self.html [ Failure Pass ] crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/editing/selection/resources/select-across-readonly-input.js b/third_party/WebKit/LayoutTests/editing/selection/resources/select-across-readonly-input.js deleted file mode 100644 index 59686907..0000000 --- a/third_party/WebKit/LayoutTests/editing/selection/resources/select-across-readonly-input.js +++ /dev/null
@@ -1,26 +0,0 @@ - -function moveMouseToMiddleOfElement(element) -{ - eventSender.mouseMoveTo(element.offsetLeft + element.offsetWidth / 2, element.offsetTop + element.offsetHeight / 2); -} - -var inputs = document.getElementsByTagName('input'); -for (var i = 0; i < inputs.length; i++) -{ - inputs[i].style.fontSize = '1em'; - inputs[i].style.width = '7ex'; -} - -if (window.testRunner) { - if (!window.eventSender) - document.writeln('This test requires eventSender'); - else { - moveMouseToMiddleOfElement(document.getElementById('from')); - eventSender.mouseDown(); - - eventSender.leapForward(200); - - moveMouseToMiddleOfElement(document.getElementById('to')); - eventSender.mouseUp(); - } -}
diff --git a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-1.html b/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-1.html index 9ac8e7f7..ab8563d 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-1.html +++ b/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-1.html
@@ -1,12 +1,145 @@ -<!DOCTYPE> -<html> -<body> -<p>This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag.</p> -<p>To manually test, select text by a mouse drag starting in "hello" and ending in "world". Selection should only extend inside the input element.</p> -<div id="test"> -<input id="from" type="text" value="hello" readonly> -<span id="to">world</span> -</div> -<script src="resources/select-across-readonly-input.js"></script> -</body> -</html> +<!doctype html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> +<script src="../../resources/ahem.js"></script> +<script> +// This test verifies mouse drag should not cross editing boundary. + +function drag(selection) { + if (!window.eventSender) + throw 'This test requires eventSender.'; + + // Reset mouse state + eventSender.mouseMoveTo(0, 0); + eventSender.leapForward(9999); + + const from = selection.document.getElementById('from'); + eventSender.mouseMoveTo( + selection.computeLeft(from) + from.offsetWidth / 2, + selection.computeTop(from) + from.offsetHeight / 2); + eventSender.mouseDown(); + eventSender.leapForward(200); + + const to = selection.document.getElementById('to'); + eventSender.mouseMoveTo( + selection.computeLeft(to) + to.offsetWidth / 2, + selection.computeTop(to) + to.offsetHeight / 2); + eventSender.mouseUp(); +} + +const kStyle = [ + '<style>', + '* { font: 10px Ahem; }', + 'input { width: 64px; }', + '</style>', +].join(''); + +selection_test( + [ + kStyle, + '<span id="from">ABCDEF</span>', + '<span id="to">012345</span>', + ], + selection => drag(selection), + [ + kStyle, + '<span id="from">ABC^DEF</span>', + '<span id="to">012|345</span>', + ], + {dumpAs: 'flattree'}, + '1 Drag left to right from SPAN to SPAN'); + +selection_test( + [ + kStyle, + '<input id="from" readonly type="text" value="ABCDEF">', + '<span id="to">012345</span>', + ], + selection => drag(selection), + [ + kStyle, + '<input id="from" readonly type="text" value="ABCDEF">', + '<div>ABC^DEF|</div>', + '</input>', + '<span id="to">012345</span>', + ], + {dumpAs: 'flattree'}, + '2 Drag left to right from INPUT to SPAN'); + +selection_test( + [ + kStyle, + '<input id="to" readonly type="text" value="ABCDEF">', + '<span id="from">012345</span>', + ], + selection => drag(selection), + [ + kStyle, + '<input id="to" readonly type="text" value="ABCDEF">', + '<div>ABCDEF</div>', + '</input>', + '<span id="from">|012^345</span>', + ], + {dumpAs: 'flattree'}, + '3 Drag right to left from SPAN to INPUT'); + +selection_test( + [ + kStyle, + '<span id="from">012345</span>', + '<input id="to" readonly type="text" value="ABCDEF">', + ], + selection => drag(selection), + [ + kStyle, + '<span id="from">012^345|</span>', + '<input id="to" readonly type="text" value="ABCDEF">', + '<div>ABCDEF</div>', + '</input>', + ], + {dumpAs: 'flattree'}, + '4 Drag left to right from SPAN to INPUT'); + +selection_test( + [ + kStyle, + '<input id="from" readonly type="text" value="ABCDEF">', + '<span>xyz</span>', + '<input id="to" readonly type="text" value="012345">', + ], + selection => drag(selection), + [ + kStyle, + '<input id="from" readonly type="text" value="ABCDEF">', + '<div>ABC^DEF|</div>', + '</input>', + '<span>xyz</span>', + '<input id="to" readonly type="text" value="012345">', + '<div>012345</div>', + '</input>', + ], + {dumpAs: 'flattree'}, + '5 Drag left to right from INPUT to INPUT'); + +selection_test( + [ + kStyle, + '<input id="to" readonly type="text" value="ABCDEF">', + '<span>xyz</span>', + '<input id="from" readonly type="text" value="012345">', + ], + selection => drag(selection), + [ + kStyle, + '<input id="to" readonly type="text" value="ABCDEF">', + '<div>ABCDEF</div>', + '</input>', + '<span>xyz</span>', + '<input id="from" readonly type="text" value="012345">', + '<div>|012^345</div>', + '</input>', + ], + {dumpAs: 'flattree'}, + '6 Drag right to left from INPUT to INPUT'); +</script>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-2.html b/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-2.html deleted file mode 100644 index bda76f7..0000000 --- a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-2.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE> -<html> -<body> -<p>This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag.</p> -<p>To manually test, select text by a mouse drag starting in "world" and ending in "hello". Selection should not extend into the input element.</p> -<div id="test"> -<input id="to" type="text" value="hello" readonly> -<span id="from">world</span> -</div> -<script src="resources/select-across-readonly-input.js"></script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-3.html b/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-3.html deleted file mode 100644 index c67356a8..0000000 --- a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-3.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE> -<html> -<body> -<p>This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag.</p> -<p>To manually test, select text by a mouse drag starting in "hello" and ending in "world". Selection should not extend into the input element.</p> -<div id="test"> -<span id="from">hello</span> -<input id="to" type="text" value="world" readonly> -</div> -<script src="resources/select-across-readonly-input.js"></script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-4.html b/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-4.html deleted file mode 100644 index 5a77529..0000000 --- a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-4.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE> -<html> -<body> -<p>This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag.</p> -<p>To manually test, select text by a mouse drag starting in "hello" and ending in "WebKit". Selection should extend only in the input element that contains "hello".</p> -<div id="test"> -<input id="from" type="text" value="hello" readonly> -<span>world</span> -<input id="to" type="text" value="WebKit" readonly> -</div> -<script src="resources/select-across-readonly-input.js"></script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-5.html b/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-5.html deleted file mode 100644 index 0768698..0000000 --- a/third_party/WebKit/LayoutTests/editing/selection/select-across-readonly-input-5.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE> -<html> -<body> -<p>This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag.</p> -<p>To manually test, select text by a mouse drag starting in "WebKit" and ending in "hello". Selection should extend only in the input element that contains "WebKit".</p> -<div id="test"> -<input id="to" type="text" value="hello" readonly> -<span>world</span> -<input id="from" type="text" value="WebKit" readonly> -</div> -<script src="resources/select-across-readonly-input.js"></script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-001.html index 20b3278..1dd2296 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-001.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-002.html index 807711b..ac833f54 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-002.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-003.html index 48a8a691..bb9da00 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-003.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-004.html index b00b40d..7d895b8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-004.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-005.html index e3e02421..113d762 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-005.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-006.html index 240e739..0f7ba1db 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-006.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-007.html index 83ac0eb..b25d628 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-007.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-008.html index 2f1c5890..8b79b96a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-008.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-009.html index 37a81b30..482e0ee 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-009.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-010.html index c1f4d21a..6e681f46 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-010.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-011.html index f32b86e..3e086b6b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-011.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/line-breaking-011.html
@@ -11,7 +11,7 @@ color:green; width: 1em; line-height: 1em; - font-family: ahem; + font-family: Ahem; white-space: normal; font-size: 20px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/reference/line-breaking-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/reference/line-breaking-001-ref.html index b446efd..a27cbc4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/reference/line-breaking-001-ref.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/line-breaking/reference/line-breaking-001-ref.html
@@ -7,7 +7,7 @@ div { color:green; line-height: 1em; - font-family: ahem; + font-family: Ahem; font-size: 20px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-001.html index 0601978..7eaa8f3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-001.html
@@ -11,7 +11,7 @@ position: relative; width: 100px; height: 100px; - font-family: ahem; + font-family: Ahem; color: red; overflow-wrap: break-word; font-size: 25px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-001.html index a5093571..124a45f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-001.html
@@ -5,7 +5,7 @@ <title>text-align: end, direction: rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-002.html index 231c1ef5..bb63bfe 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-002.html
@@ -5,7 +5,7 @@ <title>text-align: end, direction: ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-003.html index 16745c2..9761aee 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-003.html
@@ -5,7 +5,7 @@ <title>text-align: end, dir=rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-004.html index 873f58a..d286072 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-004.html
@@ -5,7 +5,7 @@ <title>text-align: end, dir=ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-005.html index a4fbc95..7ea79a9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-005.html
@@ -5,7 +5,7 @@ <title>text-align: end, direction: rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-006.html index b9882470b..f4fe84f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-006.html
@@ -5,7 +5,7 @@ <title>text-align: end, direction: ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-007.html index 3a6f5de5..a978a479 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-007.html
@@ -5,7 +5,7 @@ <title>text-align: end, dir=rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-008.html index 0f2d530..b7cf327 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-008.html
@@ -5,7 +5,7 @@ <title>text-align: end, dir=ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-009.html index fe4c60f1..32b8623 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-009.html
@@ -5,7 +5,7 @@ <title>text-align: end, dir=auto, RTL first strong</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-010.html index 3bfd0ab9..ccfa94c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-010.html
@@ -5,7 +5,7 @@ <title>text-align: end, dir=auto, LTR first strong</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-014.html index 5cf25788..b241168138 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-014.html
@@ -5,7 +5,7 @@ <title>text-align: end, pre, dir=rtl inherited</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-015.html index 3be3bc4..a3fa03d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-015.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-015.html
@@ -5,7 +5,7 @@ <title>text-align: end, pre, dir=ltr inherited</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-016.html index 51fd4337a..eebdcf5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-016.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-016.html
@@ -5,7 +5,7 @@ <title>text-align: end, pre, dir=auto</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 24px; } .rb2 { position: absolute; bottom: 0; left: 0; background-color: orange; width: 72px; height: 24px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-017.html index 2c926322..7289f14 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-017.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-end-ref-017.html
@@ -5,7 +5,7 @@ <title>text-align: end, pre, dir=auto on surrounding block</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-001.html index 09898abf..647239e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-001.html
@@ -5,7 +5,7 @@ <title>text-align: justify, direction: rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-002.html index 0874149..c74d32c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-002.html
@@ -5,7 +5,7 @@ <title>text-align: justify, direction: ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-003.html index 5524d97..38e31fc6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-003.html
@@ -5,7 +5,7 @@ <title>text-align: justify, dir=rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-004.html index d0c58679..171fa2f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-004.html
@@ -5,7 +5,7 @@ <title>text-align: justify, dir=ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-005.html index 586cc76b2..9e2612a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-005.html
@@ -5,7 +5,7 @@ <title>text-align: justify, dir=auto, RTL first strong</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-006.html index 98bc1ba..48cc2c6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justify-ref-006.html
@@ -5,7 +5,7 @@ <title>text-align: justify, dir=auto, LTR first strong</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-001.html index cab561a..6c54f27e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-001.html
@@ -5,7 +5,7 @@ <title>text-align: justify-all, direction: rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-002.html index e5e7dfd1..15d89b04 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-002.html
@@ -5,7 +5,7 @@ <title>text-align: justify-all, direction: ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-003.html index 2325bc58..5af7230 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-003.html
@@ -5,7 +5,7 @@ <title>text-align: justify-all, dir=rtl</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-004.html index 55492ed..1c7f9c5b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-004.html
@@ -5,7 +5,7 @@ <title>text-align: justify-all, dir=ltr</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-005.html index c14f564..e61054f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-005.html
@@ -5,7 +5,7 @@ <title>text-align: justify-all, dir=auto, RTL first strong</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-006.html index a74dde6..b3a79eb9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-justifyall-ref-006.html
@@ -5,7 +5,7 @@ <title>text-align: justify-all, dir=auto, LTR first strong</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } .rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-001.html index f245af9..323ece1e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-001.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-002.html index 55ef0de..9242c57 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-002.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-003.html index bb86a7e..363e20b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-003.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-004.html index 7c41a1a..b4b24ef 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-004.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-005.html index 525dde6..9b7fbef7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-005.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-006.html index 9415a8a..8c3708d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-006.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-007.html index d22b5e7..7b00ff2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-007.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-008.html index 0c0e5eb..5773192 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-008.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-009.html index b2093bf4..3177d01 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-009.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-010.html index fed7fe00..4972f258 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-010.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-014.html index 709143d..747c5e6b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-014.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-015.html index b5a56cb04..abc8797 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-015.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-015.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-016.html index 89ec38e..fbeefd6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-016.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-016.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 24px; } .rb2 { position: absolute; bottom: 0; right: 0; background-color: orange; width: 72px; height: 24px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-017.html index 8408a30..f802d49 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-017.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/reference/text-align-start-ref-017.html
@@ -7,7 +7,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-001.html index 7aa503d..b7baac8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-001.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-002.html index 2b63d6c..e080879c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-002.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-003.html index a343bda..4402bf4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-003.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-004.html index ea19883..cca16fe8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-004.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-005.html index 9db8726..9fe2dae 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-005.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-006.html index 4278474..3ea9fdc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-006.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-007.html index 7b775d0..403770f9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-007.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-008.html index 3b74c4d..8c6e5ae 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-008.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-009.html index d33dd8f7..c67fe23 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-009.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-010.html index 6a3f9bde..abcb7c07 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-010.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-014.html index 382018e..aff33e2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-014.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-015.html index 4c6a390..c5d6334 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-015.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-015.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-016.html index f66ff4f..b646102 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-016.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-016.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 24px; } #rb2 { position: absolute; bottom: 0; left: 0; background-color: orange; width: 72px; height: 24px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-017.html index 3939952..9787c3e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-017.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-end-017.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: end; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-001.html index 6a21b34..619f5a0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-001.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-002.html index 3222825..0b6b4dd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-002.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-003.html index 6badf69..3a0eeff 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-003.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-004.html index 573a3a50..6389e162 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-004.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-005.html index 0f8a4c4..e097796ae 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-005.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-006.html index 3188333..79aee25 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justify-006.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-001.html index 1a5fd5a..93709307 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-001.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify-all; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-002.html index f45f7d35..22898152 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-002.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify-all; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-003.html index dd13d5e..cc21296 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-003.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify-all; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-004.html index 2b5707a08..d483941 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-004.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify-all; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-005.html index 451f58f..edc271c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-005.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify-all; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; left: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-006.html index 14ee7372..63e4b3a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-justifyall-006.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify-all; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 399px; color: orange; font: 24px/24px Ahem; } .ref { text-align: right; position: relative; height:72px; } .rb { position: absolute; background-color: orange; width: 72px; } #rb1 { top: 0; right: 0; height: 48px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-001.html index 00d13dbc5..40c6aba 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-001.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-002.html index 0779f70..5e2791d6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-002.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-003.html index 953bd65..2e1d667 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-003.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-004.html index 464f7750c..00146305 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-004.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 300px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 24px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 120px; height: 24px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-005.html index dc8b2c0..55fe596 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-005.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; direction: rtl; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-006.html index 800380f1..fa9fcc64 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-006.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; direction: ltr; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-007.html index 3c7e34a..0774716b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-007.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-008.html index 8eebf98..ba5e78ccd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-008.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-009.html index 8af677d..55753ad 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-009.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; right: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-010.html index c01ae719..623b3ec7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-010.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-014.html index 08520956..ac451de 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-014.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; right: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-015.html index 9824cee..0b2f909 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-015.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-015.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-016.html index c412365d..3b8d858 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-016.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-016.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 24px; } #rb2 { position: absolute; bottom: 0; right: 0; background-color: orange; width: 72px; height: 24px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-017.html index e422abd..5733002 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-017.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-align/text-align-start-017.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: start; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 48px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 48px; } </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/reference/text-justify-ref-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/reference/text-justify-ref-001.html index c5ce89091..2a214057 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/reference/text-justify-ref-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/reference/text-justify-ref-001.html
@@ -5,7 +5,7 @@ <title>text-justify: none</title> <link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> <style type='text/css'> -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } .rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } .rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-001.html index 4af1df92..3e2a0d8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-001.html
@@ -10,7 +10,7 @@ <style type='text/css'> .test { text-align: justify; text-justify: none; } /* the CSS below is not part of the test */ -.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px ahem; } +.test, .ref { border: 1px solid orange; margin: 20px; width: 290px; color: orange; font: 24px/24px Ahem; } .ref { position: relative; height: 72px; } #rb1 { position: absolute; top: 0; left: 0; background-color: orange; width: 72px; height: 72px; } #rb2 { position: absolute; top: 0; left: 96px; background-color: orange; width: 72px; height: 72px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-002.html index b3e9700..ef16eaa 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-002.html
@@ -9,7 +9,7 @@ <style type='text/css'> .test { text-align: justify; text-justify: inter-character; } /* the CSS below is not part of the test */ -.test { border: 1px solid blue; margin: 20px; width: 290px; color: blue; font: 24px/24px ahem; } +.test { border: 1px solid blue; margin: 20px; width: 290px; color: blue; font: 24px/24px Ahem; } </style> </head> <body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-003.html index 6381a96..6d181fa 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-justify/text-justify-003.html
@@ -9,7 +9,7 @@ <style type='text/css'> .test { text-align: justify; text-justify: distribute; } /* the CSS below is not part of the test */ -.test { border: 1px solid blue; margin: 20px; width: 290px; color: blue; font: 24px/24px ahem; } +.test { border: 1px solid blue; margin: 20px; width: 290px; color: blue; font: 24px/24px Ahem; } </style> </head> <body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-001.html index 6a1893f..31486f8f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-001.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-002.html index 891527f..c0db9e67 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-002.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-003.html index 56d3080..e5d0a59c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-003.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-004.html index b4b3b459..3be7a7d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-004.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-005.html index bf04625..487defb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-005.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-006.html index 8802c30..d725a2d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-006.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-007.html index 29b356c1..de69880 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-007.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-008.html index 61ccaae34..e739a21 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-008.html
@@ -9,7 +9,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-009.html index 2aa8cd2..a70ad8ff 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-009.html
@@ -9,7 +9,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-010.html index 90f2005..c00fe74 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-010.html
@@ -9,7 +9,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-011.html index 6659e324..5f86cff5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-011.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-011.html
@@ -9,7 +9,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-012.html index d96be79..2d322aa 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-012.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-012.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-013.html index 6e3b6db..9de1f071 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-013.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-013.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-014.html index 2275201..5da564d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/pre-wrap-014.html
@@ -8,7 +8,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/pre-wrap-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/pre-wrap-001-ref.html index 21fe887..8a8b513 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/pre-wrap-001-ref.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/pre-wrap-001-ref.html
@@ -5,7 +5,7 @@ <style> div { font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; color: green; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/textarea-pre-wrap-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/textarea-pre-wrap-001-ref.html index 8951c3db..d09873a6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/textarea-pre-wrap-001-ref.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/textarea-pre-wrap-001-ref.html
@@ -20,7 +20,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; color: green; white-space: pre;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-001.html index 2c41682..6c7f605 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-001.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-002.html index bd411d9..340462bc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-002.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-003.html index 81f7a5a..655b1d42 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-003.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-004.html index c29ceed2..5e8d5054 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-004.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-005.html index 8137ac6..2f4d54c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-005.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-006.html index b06947c8..7805740 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-006.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-007.html index c678570..c7e5067 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-007.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-008.html index 1361bf1..71eca500 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-008.html
@@ -20,7 +20,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-009.html index cecaadb..aedca630 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-009.html
@@ -20,7 +20,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-010.html index 7d41fee8..7c5d138 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-010.html
@@ -20,7 +20,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-011.html index 96d121f..d60348d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-011.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-011.html
@@ -20,7 +20,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html index 85fcfee..3177a7b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html index fd3b26b1..05afb06 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-014.html index 881fffe1..5c4f33a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/textarea-pre-wrap-014.html
@@ -19,7 +19,7 @@ overflow: hidden; /* I don't want scrollbars, and overflow:visible isn't typically supported on textarea */ font-size: 20px; - font-family: ahem; + font-family: Ahem; line-height: 1em; white-space: pre-wrap; color: green;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/iterable.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/iterable.tentative.html index 08dc11e..085319b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/iterable.tentative.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/iterable.tentative.html
@@ -47,4 +47,13 @@ assert_style_value_array_equals(values[2], [new CSSUnparsedValue([' C'])]); }, 'StylePropertyMap iterator returns custom properties with the correct CSSStyleValue'); +test(t => { + // This is to test for https://github.com/w3c/css-houdini-drafts/issues/700 + const styleMap = createInlineStyleMap(t, '--豈: 豈; --💩: 💩;'); + const keys = [...styleMap.keys()]; + + assert_array_equals(keys, ['--💩', '--豈']); +}, 'StylePropertyMap sorts custom properties in increasing' + +'code-point order'); + </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html new file mode 100644 index 0000000..fd15186 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-node-onerror.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<html> + <head> + <title> + Test onprocessorerror handler in AudioWorkletNode + </title> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> + <script src="../../../webaudio-resources/audit.js"></script> + <script src="audio-worklet-common.js"></script> + </head> + <body> + <script id="layout-test-code"> + // TODO(hongchan): remove this assertion when AudioWorklet shipped. + assertAudioWorklet(); + + let audit = Audit.createTaskRunner(); + + const sampleRate = 48000; + const renderLength = sampleRate * 0.1; + + let context = new OfflineAudioContext(1, renderLength, sampleRate); + + // Test |onprocessorerror| called upon failure of processor constructor. + audit.define('constructor-error', + (task, should) => { + let constructorErrorWorkletNode = + new AudioWorkletNode(context, 'constructor-error'); + constructorErrorWorkletNode.onprocessorerror = () => { + // Without 'processorerror' event callback, this test will be + // timed out. + task.done(); + }; + }); + + // Test |onprocessorerror| called upon failure of process() method. + audit.define('process-error', + (task, should) => { + let processErrorWorkletNode = + new AudioWorkletNode(context, 'process-error'); + processErrorWorkletNode.connect(context.destination); + processErrorWorkletNode.onprocessorerror = () => { + // Without 'processorerror' event callback, this test will be + // timed out. + task.done(); + }; + + context.startRendering(); + }); + + // 'error-processor.js' contains 2 class definitions represents an error + // in the constructor and an error in the process method respectively. + context.audioWorklet.addModule('error-processor.js').then(() => { + audit.run(); + }); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-processor-state.html b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-processor-state.html deleted file mode 100644 index c1c51740..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/audio-worklet-processor-state.html +++ /dev/null
@@ -1,121 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title> - Test AudioWorkletProcessorState in AudioWorkletNode - </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../../../webaudio-resources/audit.js"></script> - <script src="audio-worklet-common.js"></script> - </head> - <body> - <script id="layout-test-code"> - // TODO(hongchan): remove this assertion when AudioWorklet shipped. - assertAudioWorklet(); - - let audit = Audit.createTaskRunner(); - - const sampleRate = 48000; - const renderLength = sampleRate * 0.1; - - // Test "pending", "running" and "stopped" state transition. - audit.define('pending-running-stopped', - (task, should) => { - let context = new OfflineAudioContext(1, renderLength, sampleRate); - context.audioWorklet.addModule('state-processor.js').then(() => { - let timedWorkletNode = new AudioWorkletNode(context, 'timed'); - - // The construction of associated processor has not been - // completed. In this state, no audio processing can happen and - // all messages to the processor will be queued. - should(timedWorkletNode.processorState, - 'Checking the processor state upon the constructor call') - .beEqualTo('pending'); - - timedWorkletNode.connect(context.destination); - - // Checks the handler of |onprocessorstatechange|. Because the - // processor script is correct, the |running| state change MUST - // be fired. - let isFirstPhase = true; - timedWorkletNode.onprocessorstatechange = () => { - // The first phase should be "running". - if (isFirstPhase) { - should(timedWorkletNode.processorState, - 'Checking the processor state upon ' + - 'processorstatechange event') - .beEqualTo('running'); - isFirstPhase = false; - } else { - // The second phase in this test must be "stopped". - should(timedWorkletNode.processorState, - 'Checking the processor state after ' + - 'processor stopped processing') - .beEqualTo('stopped'); - task.done(); - } - }; - - context.startRendering(); - }); - }); - - // Test the error state caused by the failure of processor constructor. - audit.define('constructor-error', - (task, should) => { - let context = new OfflineAudioContext(1, renderLength, sampleRate); - context.audioWorklet.addModule('state-processor.js').then(() => { - let constructorErrorWorkletNode = - new AudioWorkletNode(context, 'constructor-error'); - should(constructorErrorWorkletNode.processorState, - 'constructorErrorWorkletNode.processorState after ' + - 'its construction') - .beEqualTo('pending'); - constructorErrorWorkletNode.onprocessorstatechange = () => { - should(constructorErrorWorkletNode.processorState, - 'workletNode.processorState upon processorstatechange ' + - 'event after the failure from processor.constructor()') - .beEqualTo('error'); - task.done(); - }; - }); - }); - - // Test the error state caused by the failure of processor's process() - // function. - audit.define('process-error', - (task, should) => { - let context = new OfflineAudioContext(1, renderLength, sampleRate); - context.audioWorklet.addModule('state-processor.js').then(() => { - let processErrorWorkletNode = - new AudioWorkletNode(context, 'process-error'); - should(processErrorWorkletNode.processorState, - 'processErrorWorkletNode.processorState after ' + - 'its construction') - .beEqualTo('pending'); - - processErrorWorkletNode.connect(context.destination); - - let isFirstPhase = true; - processErrorWorkletNode.onprocessorstatechange = () => { - if (isFirstPhase) { - // Ignore the first state change event, which is "running"; - isFirstPhase = false; - } else { - should(processErrorWorkletNode.processorState, - 'workletNode.processorState upon processorstatechange ' + - 'event after the failure from processor.process()') - .beEqualTo('error'); - task.done(); - } - }; - - context.startRendering(); - }); - }); - - audit.run(); - </script> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/error-processor.js b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/error-processor.js new file mode 100644 index 0000000..3b010db --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/error-processor.js
@@ -0,0 +1,33 @@ +/** + * @class ConstructorErrorProcessor + * @extends AudioWorkletProcessor + */ +class ConstructorErrorProcessor extends AudioWorkletProcessor { + constructor() { + throw 'ConstructorErrorProcessor: an error thrown from constructor.'; + } + + process() { + return true; + } +} + + +/** + * @class ProcessErrorProcessor + * @extends AudioWorkletProcessor + */ +class ProcessErrorProcessor extends AudioWorkletProcessor { + constructor() { + super(); + } + + process() { + throw 'ProcessErrorProcessor: an error throw from process method.'; + return true; + } +} + + +registerProcessor('constructor-error', ConstructorErrorProcessor); +registerProcessor('process-error', ProcessErrorProcessor);
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/state-processor.js b/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/state-processor.js deleted file mode 100644 index 66213c5..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/state-processor.js +++ /dev/null
@@ -1,54 +0,0 @@ -/** - * @class TimedProcessor - * @extends AudioWorkletProcessor - * - * This processor class is for the life cycle and the processor state event. - * It only lives for 1 render quantum. - */ -class TimedProcessor extends AudioWorkletProcessor { - constructor() { - super(); - this.createdAt_ = currentTime; - this.lifetime_ = 128 / sampleRate; - } - - process() { - return currentTime - this.createdAt_ > this.lifetime_ ? false : true; - } -} - - -/** - * @class ConstructorErrorProcessor - * @extends AudioWorkletProcessor - */ -class ConstructorErrorProcessor extends AudioWorkletProcessor { - constructor() { - throw 'ConstructorErrorProcessor: an error thrown from constructor.'; - } - - process() { - return true; - } -} - - -/** - * @class ProcessErrorProcessor - * @extends AudioWorkletProcessor - */ -class ProcessErrorProcessor extends AudioWorkletProcessor { - constructor() { - super(); - } - - process() { - throw 'ProcessErrorProcessor: an error throw from process method.'; - return true; - } -} - - -registerProcessor('timed', TimedProcessor); -registerProcessor('constructor-error', ConstructorErrorProcessor); -registerProcessor('process-error', ProcessErrorProcessor);
diff --git a/third_party/WebKit/LayoutTests/paint/background/scrolling-contents-background-clip-layer-crash.html b/third_party/WebKit/LayoutTests/paint/background/scrolling-contents-background-clip-layer-crash.html new file mode 100644 index 0000000..5034a62 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/background/scrolling-contents-background-clip-layer-crash.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script>test(function(){});</script> +<div style="will-change: transform; width: 100px; height: 100px; background: blue; overflow: scroll; + border-radius: 5px; border: 2px dotted green"> + <div style="width: 200px; height: 200px"> + Content + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/absolute-with-transform-move-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/absolute-with-transform-move-expected.html new file mode 100644 index 0000000..688dcde --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/absolute-with-transform-move-expected.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<div id="target" style="width: 100px; height: 100px; left: 100px; background: green; position: absolute; transform: scale(0.9)"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/absolute-with-transform-move.html b/third_party/WebKit/LayoutTests/paint/invalidation/absolute-with-transform-move.html new file mode 100644 index 0000000..e311684 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/absolute-with-transform-move.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<script> +runAfterLayoutAndPaint(function() { + target.style.left = '100px'; +}, true); +</script> +<div id="target" style="width: 100px; height: 100px; background: green; position: absolute; transform: scale(0.9)"></div>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-1-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-1-expected.png deleted file mode 100644 index 60983d25..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-1-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-1-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-1-expected.txt deleted file mode 100644 index e525439..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-1-expected.txt +++ /dev/null
@@ -1,27 +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 784x40 - LayoutText {#text} at (0,0) size 776x39 - text run at (0,0) width 776: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse" - text run at (0,20) width 32: "drag." - LayoutBlockFlow {P} at (0,56) size 784x40 - LayoutText {#text} at (0,0) size 773x39 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should only extend inside" - text run at (0,20) width 112: "the input element." - LayoutBlockFlow {DIV} at (0,112) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (63,3) size 4x19 - text run at (63,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 37x19 - LayoutText {#text} at (67,3) size 37x19 - text run at (67,3) width 37: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (10,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-2-expected.png deleted file mode 100644 index 58678db..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-2-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-2-expected.txt deleted file mode 100644 index 3b81551..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-2-expected.txt +++ /dev/null
@@ -1,27 +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 784x40 - LayoutText {#text} at (0,0) size 776x39 - text run at (0,0) width 776: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse" - text run at (0,20) width 32: "drag." - LayoutBlockFlow {P} at (0,56) size 784x40 - LayoutText {#text} at (0,0) size 775x39 - text run at (0,0) width 775: "To manually test, select text by a mouse drag starting in \"world\" and ending in \"hello\". Selection should not extend into the" - text run at (0,20) width 89: "input element." - LayoutBlockFlow {DIV} at (0,112) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (63,3) size 4x19 - text run at (63,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 37x19 - LayoutText {#text} at (67,3) size 37x19 - text run at (67,3) width 37: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (10,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -selection start: position 0 of child 2 {#text} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {SPAN} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-3-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-3-expected.png deleted file mode 100644 index 7117c82..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-3-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-3-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-3-expected.txt deleted file mode 100644 index d96c8d2..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-3-expected.txt +++ /dev/null
@@ -1,27 +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 784x40 - LayoutText {#text} at (0,0) size 776x39 - text run at (0,0) width 776: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse" - text run at (0,20) width 32: "drag." - LayoutBlockFlow {P} at (0,56) size 784x40 - LayoutText {#text} at (0,0) size 775x39 - text run at (0,0) width 775: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should not extend into the" - text run at (0,20) width 89: "input element." - LayoutBlockFlow {DIV} at (0,112) size 784x25 - LayoutInline {SPAN} at (0,0) size 31x19 - LayoutText {#text} at (0,3) size 31x19 - text run at (0,3) width 31: "hello" - LayoutText {#text} at (31,3) size 4x19 - text run at (31,3) width 4: " " - LayoutTextControl {INPUT} at (35,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (45,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 39x18 - text run at (0,0) width 39: "world" -selection start: position 2 of child 0 {#text} of child 1 {SPAN} of child 5 {DIV} of body -selection end: position 1 of child 2 {#text} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-4-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-4-expected.png deleted file mode 100644 index 73203c6..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-4-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-4-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-4-expected.txt deleted file mode 100644 index cc2af63..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-4-expected.txt +++ /dev/null
@@ -1,34 +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 784x40 - LayoutText {#text} at (0,0) size 776x39 - text run at (0,0) width 776: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse" - text run at (0,20) width 32: "drag." - LayoutBlockFlow {P} at (0,56) size 784x40 - LayoutText {#text} at (0,0) size 783x39 - text run at (0,0) width 783: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"WebKit\". Selection should extend only in the" - text run at (0,20) width 221: "input element that contains \"hello\"." - LayoutBlockFlow {DIV} at (0,112) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (63,3) size 4x19 - text run at (63,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 37x19 - LayoutText {#text} at (67,3) size 37x19 - text run at (67,3) width 37: "world" - LayoutText {#text} at (104,3) size 4x19 - text run at (104,3) width 4: " " - LayoutTextControl {INPUT} at (108,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (10,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -layer at (118,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 52x18 - text run at (0,0) width 52: "WebKit" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-5-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-5-expected.png deleted file mode 100644 index 3fbbddd..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-5-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-5-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-5-expected.txt deleted file mode 100644 index 36b6652..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/select-across-readonly-input-5-expected.txt +++ /dev/null
@@ -1,34 +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 784x40 - LayoutText {#text} at (0,0) size 776x39 - text run at (0,0) width 776: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse" - text run at (0,20) width 32: "drag." - LayoutBlockFlow {P} at (0,56) size 784x40 - LayoutText {#text} at (0,0) size 783x39 - text run at (0,0) width 783: "To manually test, select text by a mouse drag starting in \"WebKit\" and ending in \"hello\". Selection should extend only in the" - text run at (0,20) width 239: "input element that contains \"WebKit\"." - LayoutBlockFlow {DIV} at (0,112) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (63,3) size 4x19 - text run at (63,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 37x19 - LayoutText {#text} at (67,3) size 37x19 - text run at (67,3) width 37: "world" - LayoutText {#text} at (104,3) size 4x19 - text run at (104,3) width 4: " " - LayoutTextControl {INPUT} at (108,0) size 63x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (10,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -layer at (118,123) size 59x19 - LayoutBlockFlow {DIV} at (2,3) size 59x19 - LayoutText {#text} at (0,0) size 52x18 - text run at (0,0) width 52: "WebKit" -selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body -selection end: position 3 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/acid3-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/acid3-expected.txt index cbcc7ba..147227d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/acid3-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/acid3-expected.txt
@@ -212,7 +212,7 @@ text run at (0,2272) width 8: ">" layer at (57,350) size 0x0 LayoutIFrame (floating) {IFRAME} at (0,0) size 0x0 - layer at (0,0) size 0x0 + layer at (0,0) size 0x0 scrollWidth 1 scrollHeight 8 LayoutView at (0,0) size 0x0 layer at (0,0) size 0x8 LayoutBlockFlow {HTML} at (0,0) size 0x8
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-1-expected.png deleted file mode 100644 index ccbfd4a6..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-1-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-1-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-1-expected.txt deleted file mode 100644 index c4b3e76e..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-1-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 745x36 - text run at (0,0) width 745: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should only extend" - text run at (0,18) width 158: "inside the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-2-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-2-expected.png deleted file mode 100644 index a366cf91..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-2-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-2-expected.txt deleted file mode 100644 index 41ba003..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-2-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 766x36 - text run at (0,0) width 766: "To manually test, select text by a mouse drag starting in \"world\" and ending in \"hello\". Selection should not extend into" - text run at (0,18) width 116: "the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -selection start: position 0 of child 2 {#text} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {SPAN} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-3-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-3-expected.png deleted file mode 100644 index 1141017..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-3-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-3-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-3-expected.txt deleted file mode 100644 index 2e67fdbc..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-3-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 766x36 - text run at (0,0) width 766: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should not extend into" - text run at (0,18) width 116: "the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutInline {SPAN} at (0,0) size 32x18 - LayoutText {#text} at (0,4) size 32x18 - text run at (0,4) width 32: "hello" - LayoutText {#text} at (31,4) size 5x18 - text run at (31,4) width 5: " " - LayoutTextControl {INPUT} at (35.98,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (47,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 41x18 - text run at (0,0) width 41: "world" -selection start: position 2 of child 0 {#text} of child 1 {SPAN} of child 5 {DIV} of body -selection end: position 1 of child 2 {#text} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-4-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-4-expected.png deleted file mode 100644 index 73dd52f5..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-4-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-4-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-4-expected.txt deleted file mode 100644 index 4c70d07..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-4-expected.txt +++ /dev/null
@@ -1,34 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 773x36 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"WebKit\". Selection should extend only in" - text run at (0,18) width 250: "the input element that contains \"hello\"." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (100,4) size 5x18 - text run at (100,4) width 5: " " - LayoutTextControl {INPUT} at (104.17,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -layer at (115,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 53x18 - text run at (0,0) width 53: "WebKit" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-5-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-5-expected.png deleted file mode 100644 index 9a2f0df..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-5-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-5-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-5-expected.txt deleted file mode 100644 index b51e70e..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/selection/select-across-readonly-input-5-expected.txt +++ /dev/null
@@ -1,34 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 773x36 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"WebKit\" and ending in \"hello\". Selection should extend only in" - text run at (0,18) width 267: "the input element that contains \"WebKit\"." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (100,4) size 5x18 - text run at (100,4) width 5: " " - LayoutTextControl {INPUT} at (104.17,0) size 58.84x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -layer at (115,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.84x18 - LayoutText {#text} at (0,0) size 53x18 - text run at (0,0) width 53: "WebKit" -selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-1-expected.png deleted file mode 100644 index 6e3d964..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-1-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-1-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-1-expected.txt deleted file mode 100644 index 3b45dc4..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-1-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 745x36 - text run at (0,0) width 745: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should only extend" - text run at (0,18) width 158: "inside the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 37x18 - text run at (0,0) width 37: "hello" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-2-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-2-expected.png deleted file mode 100644 index 54b94a1..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-2-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-2-expected.txt deleted file mode 100644 index 453d8c1d..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-2-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 766x36 - text run at (0,0) width 766: "To manually test, select text by a mouse drag starting in \"world\" and ending in \"hello\". Selection should not extend into" - text run at (0,18) width 116: "the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 37x18 - text run at (0,0) width 37: "hello" -selection start: position 0 of child 2 {#text} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {SPAN} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-3-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-3-expected.png deleted file mode 100644 index ef897d08..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-3-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-3-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-3-expected.txt deleted file mode 100644 index 0caaf03..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-3-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 766x36 - text run at (0,0) width 766: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should not extend into" - text run at (0,18) width 116: "the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutInline {SPAN} at (0,0) size 32x18 - LayoutText {#text} at (0,4) size 32x18 - text run at (0,4) width 32: "hello" - LayoutText {#text} at (31,4) size 5x18 - text run at (31,4) width 5: " " - LayoutTextControl {INPUT} at (35.98,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (47,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 42x18 - text run at (0,0) width 42: "world" -selection start: position 2 of child 0 {#text} of child 1 {SPAN} of child 5 {DIV} of body -selection end: position 1 of child 2 {#text} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-4-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-4-expected.png deleted file mode 100644 index 52f58d1..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-4-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-4-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-4-expected.txt deleted file mode 100644 index 3f1416b9d..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-4-expected.txt +++ /dev/null
@@ -1,34 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 773x36 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"WebKit\". Selection should extend only in" - text run at (0,18) width 250: "the input element that contains \"hello\"." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (100,4) size 5x18 - text run at (100,4) width 5: " " - LayoutTextControl {INPUT} at (104.28,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 37x18 - text run at (0,0) width 37: "hello" -layer at (115,115) size 53x18 scrollWidth 54 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 54x18 - text run at (0,0) width 54: "WebKit" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-5-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-5-expected.png deleted file mode 100644 index a7b336d..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-5-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-5-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-5-expected.txt deleted file mode 100644 index 6c657396..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/select-across-readonly-input-5-expected.txt +++ /dev/null
@@ -1,34 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 773x36 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"WebKit\" and ending in \"hello\". Selection should extend only in" - text run at (0,18) width 267: "the input element that contains \"WebKit\"." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (100,4) size 5x18 - text run at (100,4) width 5: " " - LayoutTextControl {INPUT} at (104.28,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 37x18 - text run at (0,0) width 37: "hello" -layer at (115,115) size 53x18 scrollWidth 54 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 54x18 - text run at (0,0) width 54: "WebKit" -selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-1-expected.png deleted file mode 100644 index 93c5643..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-1-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-1-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-1-expected.txt deleted file mode 100644 index 04c26f9..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-1-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 745x36 - text run at (0,0) width 745: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should only extend" - text run at (0,18) width 158: "inside the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-2-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-2-expected.png deleted file mode 100644 index 8770f40..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-2-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-2-expected.txt deleted file mode 100644 index 07ba7e4..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-2-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 766x36 - text run at (0,0) width 766: "To manually test, select text by a mouse drag starting in \"world\" and ending in \"hello\". Selection should not extend into" - text run at (0,18) width 116: "the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -selection start: position 0 of child 2 {#text} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {SPAN} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-3-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-3-expected.png deleted file mode 100644 index 5d855e5c..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-3-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-3-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-3-expected.txt deleted file mode 100644 index 123ac765..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-3-expected.txt +++ /dev/null
@@ -1,27 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 766x36 - text run at (0,0) width 766: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should not extend into" - text run at (0,18) width 116: "the input element." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutInline {SPAN} at (0,0) size 32x18 - LayoutText {#text} at (0,4) size 32x18 - text run at (0,4) width 32: "hello" - LayoutText {#text} at (31,4) size 5x18 - text run at (31,4) width 5: " " - LayoutTextControl {INPUT} at (35.98,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (47,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 40x18 - text run at (0,0) width 40: "world" -selection start: position 2 of child 0 {#text} of child 1 {SPAN} of child 5 {DIV} of body -selection end: position 1 of child 2 {#text} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-4-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-4-expected.png deleted file mode 100644 index eff97f9..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-4-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-4-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-4-expected.txt deleted file mode 100644 index c530220..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-4-expected.txt +++ /dev/null
@@ -1,34 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 773x36 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"WebKit\". Selection should extend only in" - text run at (0,18) width 250: "the input element that contains \"hello\"." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (100,4) size 5x18 - text run at (100,4) width 5: " " - LayoutTextControl {INPUT} at (104.28,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -layer at (115,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 53x18 - text run at (0,0) width 53: "WebKit" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-5-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-5-expected.png deleted file mode 100644 index 1edf22f..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-5-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-5-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-5-expected.txt deleted file mode 100644 index c7d2076f..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/select-across-readonly-input-5-expected.txt +++ /dev/null
@@ -1,34 +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 744x36 - text run at (0,0) width 744: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a" - text run at (0,18) width 79: "mouse drag." - LayoutBlockFlow {P} at (0,52) size 784x36 - LayoutText {#text} at (0,0) size 773x36 - text run at (0,0) width 773: "To manually test, select text by a mouse drag starting in \"WebKit\" and ending in \"hello\". Selection should extend only in" - text run at (0,18) width 267: "the input element that contains \"WebKit\"." - LayoutBlockFlow {DIV} at (0,104) size 784x24 - LayoutTextControl {INPUT} at (0,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (58,4) size 5x18 - text run at (58,4) width 5: " " - LayoutInline {SPAN} at (0,0) size 39x18 - LayoutText {#text} at (62,4) size 39x18 - text run at (62,4) width 39: "world" - LayoutText {#text} at (100,4) size 5x18 - text run at (100,4) width 5: " " - LayoutTextControl {INPUT} at (104.28,0) size 58.95x24 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (11,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 35x18 - text run at (0,0) width 35: "hello" -layer at (115,115) size 53x18 - LayoutBlockFlow {DIV} at (3,3) size 52.95x18 - LayoutText {#text} at (0,0) size 53x18 - text run at (0,0) width 53: "WebKit" -selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/acid3-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/acid3-expected.txt index d99c93f..5e9bfba 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/acid3-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/acid3-expected.txt
@@ -212,7 +212,7 @@ text run at (0,2130) width 8: ">" layer at (57,350) size 0x0 LayoutIFrame (floating) {IFRAME} at (0,0) size 0x0 - layer at (0,0) size 0x0 + layer at (0,0) size 0x0 scrollWidth 1 scrollHeight 8 LayoutView at (0,0) size 0x0 layer at (0,0) size 0x8 LayoutBlockFlow {HTML} at (0,0) size 0x8
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-1-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-1-expected.png deleted file mode 100644 index 78a24fa..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-1-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-1-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-1-expected.txt deleted file mode 100644 index 55f005e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-1-expected.txt +++ /dev/null
@@ -1,26 +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 784x20 - LayoutText {#text} at (0,0) size 779x19 - text run at (0,0) width 779: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag." - LayoutBlockFlow {P} at (0,36) size 784x40 - LayoutText {#text} at (0,0) size 776x39 - text run at (0,0) width 776: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should only extend inside the input" - text run at (0,20) width 50: "element." - LayoutBlockFlow {DIV} at (0,92) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (56,3) size 4x19 - text run at (56,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 35x19 - LayoutText {#text} at (60,3) size 35x19 - text run at (60,3) width 35: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (10,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 32x18 - text run at (0,0) width 32: "hello" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-2-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-2-expected.png deleted file mode 100644 index 4016906..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-2-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-2-expected.txt deleted file mode 100644 index 14a53e7..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-2-expected.txt +++ /dev/null
@@ -1,26 +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 784x20 - LayoutText {#text} at (0,0) size 779x19 - text run at (0,0) width 779: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag." - LayoutBlockFlow {P} at (0,36) size 784x40 - LayoutText {#text} at (0,0) size 758x39 - text run at (0,0) width 758: "To manually test, select text by a mouse drag starting in \"world\" and ending in \"hello\". Selection should not extend into the input" - text run at (0,20) width 50: "element." - LayoutBlockFlow {DIV} at (0,92) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (56,3) size 4x19 - text run at (56,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 35x19 - LayoutText {#text} at (60,3) size 35x19 - text run at (60,3) width 35: "world" - LayoutText {#text} at (0,0) size 0x0 -layer at (10,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 32x18 - text run at (0,0) width 32: "hello" -selection start: position 0 of child 2 {#text} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {SPAN} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-3-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-3-expected.png deleted file mode 100644 index f843e7f..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-3-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-3-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-3-expected.txt deleted file mode 100644 index a3f0f48..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-3-expected.txt +++ /dev/null
@@ -1,26 +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 784x20 - LayoutText {#text} at (0,0) size 779x19 - text run at (0,0) width 779: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag." - LayoutBlockFlow {P} at (0,36) size 784x40 - LayoutText {#text} at (0,0) size 758x39 - text run at (0,0) width 758: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"world\". Selection should not extend into the input" - text run at (0,20) width 50: "element." - LayoutBlockFlow {DIV} at (0,92) size 784x25 - LayoutInline {SPAN} at (0,0) size 28x19 - LayoutText {#text} at (0,3) size 28x19 - text run at (0,3) width 28: "hello" - LayoutText {#text} at (28,3) size 4x19 - text run at (28,3) width 4: " " - LayoutTextControl {INPUT} at (32,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (42,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 37x18 - text run at (0,0) width 37: "world" -selection start: position 2 of child 0 {#text} of child 1 {SPAN} of child 5 {DIV} of body -selection end: position 1 of child 2 {#text} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-4-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-4-expected.png deleted file mode 100644 index fb3eda1b..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-4-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-4-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-4-expected.txt deleted file mode 100644 index 37837a0..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-4-expected.txt +++ /dev/null
@@ -1,33 +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 784x20 - LayoutText {#text} at (0,0) size 779x19 - text run at (0,0) width 779: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag." - LayoutBlockFlow {P} at (0,36) size 784x40 - LayoutText {#text} at (0,0) size 765x39 - text run at (0,0) width 765: "To manually test, select text by a mouse drag starting in \"hello\" and ending in \"WebKit\". Selection should extend only in the input" - text run at (0,20) width 171: "element that contains \"hello\"." - LayoutBlockFlow {DIV} at (0,92) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (56,3) size 4x19 - text run at (56,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 35x19 - LayoutText {#text} at (60,3) size 35x19 - text run at (60,3) width 35: "world" - LayoutText {#text} at (95,3) size 4x19 - text run at (95,3) width 4: " " - LayoutTextControl {INPUT} at (99,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (10,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 32x18 - text run at (0,0) width 32: "hello" -layer at (109,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 52x18 - text run at (0,0) width 52: "WebKit" -selection start: position 4 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body -selection end: position 5 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 1 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-5-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-5-expected.png deleted file mode 100644 index 022ce11a..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-5-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-5-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-5-expected.txt deleted file mode 100644 index 3ec882c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/select-across-readonly-input-5-expected.txt +++ /dev/null
@@ -1,33 +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 784x20 - LayoutText {#text} at (0,0) size 779x19 - text run at (0,0) width 779: "This test ensures selection that crosses the shadow DOM boundary of a readonly input element cannot be made by a mouse drag." - LayoutBlockFlow {P} at (0,36) size 784x40 - LayoutText {#text} at (0,0) size 765x39 - text run at (0,0) width 765: "To manually test, select text by a mouse drag starting in \"WebKit\" and ending in \"hello\". Selection should extend only in the input" - text run at (0,20) width 191: "element that contains \"WebKit\"." - LayoutBlockFlow {DIV} at (0,92) size 784x25 - LayoutTextControl {INPUT} at (0,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (56,3) size 4x19 - text run at (56,3) width 4: " " - LayoutInline {SPAN} at (0,0) size 35x19 - LayoutText {#text} at (60,3) size 35x19 - text run at (60,3) width 35: "world" - LayoutText {#text} at (95,3) size 4x19 - text run at (95,3) width 4: " " - LayoutTextControl {INPUT} at (99,0) size 56x25 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutText {#text} at (0,0) size 0x0 -layer at (10,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 32x18 - text run at (0,0) width 32: "hello" -layer at (109,103) size 52x19 - LayoutBlockFlow {DIV} at (2,3) size 52x19 - LayoutText {#text} at (0,0) size 52x18 - text run at (0,0) width 52: "WebKit" -selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body -selection end: position 2 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 5 {INPUT} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/acid3-expected.txt b/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/acid3-expected.txt index 0f2c4e71..7739977 100644 --- a/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/acid3-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/acid3-expected.txt
@@ -212,7 +212,7 @@ text run at (0,2272) width 8: ">" layer at (57,350) size 0x0 LayoutIFrame (floating) {IFRAME} at (0,0) size 0x0 - layer at (0,0) size 0x0 + layer at (0,0) size 0x0 scrollWidth 1 scrollHeight 8 LayoutView at (0,0) size 0x0 layer at (0,0) size 0x8 LayoutBlockFlow {HTML} at (0,0) size 0x8
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index 445fe333..969ec60d 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -734,9 +734,7 @@ interface Clipboard : EventTarget attribute @@toStringTag method constructor - method read method readText - method write method writeText interface ClipboardEvent : Event attribute @@toStringTag @@ -3939,6 +3937,7 @@ getter appName getter appVersion getter budget + getter clipboard getter connection getter cookieEnabled getter credentials
diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp deleted file mode 100644 index c43a936..0000000 --- a/third_party/WebKit/Source/bindings/modules/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ /dev/null
@@ -1,86 +0,0 @@ -/* - * Copyright (c) 2009, 2012 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 "bindings/core/v8/GeneratedCodeHelper.h" -#include "bindings/core/v8/ScriptController.h" -#include "bindings/core/v8/V8BindingForCore.h" -#include "bindings/modules/v8/V8SQLError.h" -#include "bindings/modules/v8/V8SQLStatementErrorCallback.h" -#include "bindings/modules/v8/V8SQLTransaction.h" -#include "core/dom/ExecutionContext.h" -#include "platform/wtf/Assertions.h" - -namespace blink { - -bool V8SQLStatementErrorCallback::handleEvent( - ScriptWrappable* callback_this_value, - SQLTransaction* transaction, - SQLError* error) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return true; - } - - v8::Isolate* isolate = GetIsolate(); - ScriptState::Scope scope(CallbackRelevantScriptState()); - - v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); - v8::Local<v8::Value> transaction_handle = - ToV8(transaction, argument_creation_context, isolate); - v8::Local<v8::Value> error_handle = - ToV8(error, argument_creation_context, isolate); - DCHECK(transaction_handle->IsObject()); - - v8::Local<v8::Value> argv[] = {transaction_handle, error_handle}; - - v8::TryCatch exception_catcher(isolate); - exception_catcher.SetVerbose(true); - - v8::Local<v8::Value> result; - // FIXME: This comment doesn't make much sense given what the code is actually - // doing. - // - // Step 6: If the error callback returns false, then move on to the next - // statement, if any, or onto the next overall step otherwise. Otherwise, - // the error callback did not return false, or there was no error callback. - // Jump to the last step in the overall steps. - if (!V8ScriptRunner::CallFunction( - CallbackObject().As<v8::Function>(), - ExecutionContext::From(CallbackRelevantScriptState()), - v8::Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate) - .ToLocal(&result)) - return true; - bool value; - if (!result->BooleanValue(isolate->GetCurrentContext()).To(&value)) - return true; - return value; -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni b/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni index be3af4ac..c82423d 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni +++ b/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gni
@@ -4,8 +4,4 @@ # Make the files absolute so they can be imported to anywhere. bindings_modules_v8_custom_files = - get_path_info([ - "V8CustomSQLStatementErrorCallback.cpp", - "V8ExtendableMessageEventCustom.cpp", - ], - "abspath") + get_path_info([ "V8ExtendableMessageEventCustom.cpp" ], "abspath")
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py index df3c730..53c54de 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py
@@ -146,16 +146,13 @@ idl_type_str = str(idl_type) if idl_type_str not in ['boolean', 'void']: raise Exception('We only support callbacks that return boolean or void values.') - is_custom = 'Custom' in extended_attributes - if not is_custom: - add_includes_for_operation(operation) + add_includes_for_operation(operation) call_with = extended_attributes.get('CallWith') call_with_this_handle = v8_utilities.extended_attribute_value_contains(call_with, 'ThisValue') context = { 'call_with_this_handle': call_with_this_handle, 'cpp_type': idl_type.callback_cpp_type, 'idl_type': idl_type_str, - 'is_custom': is_custom, 'name': operation.name, } context.update(arguments_context(operation.arguments,
diff --git a/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl index 743edb3..7fcb1443 100644 --- a/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/callback_function.cpp.tmpl
@@ -150,6 +150,28 @@ } {% endif %} +{{exported|replace('_EXPORT', '_TEMPLATE_EXPORT')|trim}} +v8::Maybe<{{return_cpp_type}}> V8PersistentCallbackFunction<{{cpp_class}}>::Invoke({{argument_declarations | join(', ')}}) { + return Proxy()->Invoke( + {{ + (['callback_this_value'] + + (arguments|map(attribute='name')|list) + )|join(', ') + }}); +} + +{% if idl_type == 'void' %} +{{exported|replace('_EXPORT', '_TEMPLATE_EXPORT')|trim}} +void V8PersistentCallbackFunction<{{cpp_class}}>::InvokeAndReportException({{argument_declarations | join(', ')}}) { + Proxy()->InvokeAndReportException( + {{ + (['callback_this_value'] + + (arguments|map(attribute='name')|list) + )|join(', ') + }}); +} +{% endif %} + } // namespace blink {% endfilter %}{# format_blink_cpp_source_code #}
diff --git a/third_party/WebKit/Source/bindings/templates/callback_function.h.tmpl b/third_party/WebKit/Source/bindings/templates/callback_function.h.tmpl index e958ea5f..e43b7d5 100644 --- a/third_party/WebKit/Source/bindings/templates/callback_function.h.tmpl +++ b/third_party/WebKit/Source/bindings/templates/callback_function.h.tmpl
@@ -15,7 +15,7 @@ class {{forward_declaration}}; {% endfor %} -class {{exported}}{{cpp_class}} : public CallbackFunctionBase { +class {{exported}}{{cpp_class}} final : public CallbackFunctionBase { public: static {{cpp_class}}* Create(v8::Local<v8::Function> callback_function) { return new {{cpp_class}}(callback_function); @@ -33,15 +33,48 @@ void InvokeAndReportException({{argument_declarations | join(', ')}}); {% endif %} - protected: - explicit {{cpp_class}}(const {{cpp_class}}& other) - : CallbackFunctionBase(other) {} - private: explicit {{cpp_class}}(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class {{exported|replace('_EXPORT', '_TEMPLATE_CLASS_EXPORT')}}V8PersistentCallbackFunction<{{cpp_class}}> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = {{cpp_class}}; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + {{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}} + v8::Maybe<{{return_cpp_type}}> Invoke({{argument_declarations | join(', ')}}) WARN_UNUSED_RESULT; +{% if idl_type == 'void' %} + {{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}} + void InvokeAndReportException({{argument_declarations | join(', ')}}); +{% endif %} + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// {{cpp_class}} is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<{{cpp_class}}> WrapPersistent({{cpp_class}}*) = delete; + } // namespace blink #endif // {{cpp_class}}_h
diff --git a/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl index e591da0..b0d9323 100644 --- a/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/callback_interface.cpp.tmpl
@@ -10,19 +10,26 @@ namespace blink { -{# TODO(yukishiino): Remove |method.is_custom| once we support the author - function\'s return value. #} -{% for method in methods if not method.is_custom %} +{% for method in methods %} -{% set return_success = 'return' if method.cpp_type == 'void' else 'return true' %} -{% set return_failure = 'return' if method.cpp_type == 'void' else 'return false' %} - -{{method.cpp_type}} {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) { +v8::Maybe<{{method.cpp_type}}> {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - {{return_success}}; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "{{method.name}}", + "{{cpp_class}}", + "The provided callback is no longer runnable.")); + return v8::Nothing<{{method.cpp_type}}>(); } // step 7. Prepare to run script with relevant settings. @@ -32,14 +39,17 @@ {# TODO(yukishiino): Callback interface type value must make the incumbent environment alive, i.e. the reference to v8::Context must be strong. #} if (IncumbentScriptState()->GetContext().IsEmpty()) { - {{return_success}}; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "{{method.name}}", + "{{cpp_class}}", + "The provided callback is no longer runnable.")); + return v8::Nothing<{{method.cpp_type}}>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -53,7 +63,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "{{method.name}}")) .ToLocal(&value)) { - {{return_failure}}; + return v8::Nothing<{{method.cpp_type}}>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -65,7 +75,7 @@ "{{method.name}}", "{{cpp_class}}", "The provided callback is not callable.")); - {{return_failure}}; + return v8::Nothing<{{method.cpp_type}}>(); } } @@ -94,7 +104,7 @@ "{{method.name}}"); if (!IsValidEnum({{argument.name}}, {{valid_enum_variables}}, WTF_ARRAY_LENGTH({{valid_enum_variables}}), "{{argument.enum_type}}", exception_state)) { NOTREACHED(); - return false; + return v8::Nothing<{{method.cpp_type}}>(); } } #endif @@ -129,14 +139,13 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - {{return_failure}}; + return v8::Nothing<{{method.cpp_type}}>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. {% if method.idl_type == 'void' %} - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); {% else %} { ExceptionState exception_state(GetIsolate(), @@ -147,8 +156,10 @@ auto native_result = NativeValueTraits<{{idl_return_type}}>::NativeValue( GetIsolate(), call_result, exception_state); - ALLOW_UNUSED_LOCAL(native_result); - return !exception_state.HadException(); + if (exception_state.HadException()) + return v8::Nothing<{{method.cpp_type}}>(); + else + return v8::Just<{{method.cpp_type}}>(native_result); } {% endif %} } @@ -160,12 +171,14 @@ v8::TryCatch try_catch(GetIsolate()); try_catch.SetVerbose(true); - {{methods[0].name}}( - {{ - (['callback_this_value'] + - (methods[0].arguments|map(attribute='name')|list) - )|join(', ') - }}); + v8::Maybe<void> maybe_result = + {{methods[0].name}}({{ + (['callback_this_value'] + + (methods[0].arguments|map(attribute='name')|list) + )|join(', ') + }}); + // An exception if any is killed with the v8::TryCatch above. + ALLOW_UNUSED_LOCAL(maybe_result); } {% endif %}
diff --git a/third_party/WebKit/Source/bindings/templates/callback_interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/callback_interface.h.tmpl index fcd69c1..901f5d0 100644 --- a/third_party/WebKit/Source/bindings/templates/callback_interface.h.tmpl +++ b/third_party/WebKit/Source/bindings/templates/callback_interface.h.tmpl
@@ -24,11 +24,9 @@ ~{{v8_class}}() override = default; {% for method in methods %} - {# TODO(yukishiino): Change the return type to v8::Maybe<T> so that the - function returns a return value or throws an exception. #} // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - {{method.cpp_type}} {{method.name}}({{method.argument_declarations | join(', ')}}); + v8::Maybe<{{method.cpp_type}}> {{method.name}}({{method.argument_declarations | join(', ')}}) WARN_UNUSED_RESULT; {% endfor %}
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp index d165afd..33f6a63 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.cpp
@@ -20,12 +20,24 @@ namespace blink { -void V8TestCallbackInterface::voidMethod(ScriptWrappable* callback_this_value) { +v8::Maybe<void> V8TestCallbackInterface::voidMethod(ScriptWrappable* callback_this_value) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethod", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -33,14 +45,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethod", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -54,7 +69,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "voidMethod")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -66,7 +81,7 @@ "voidMethod", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -103,21 +118,32 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); } -bool V8TestCallbackInterface::booleanMethod(ScriptWrappable* callback_this_value) { +v8::Maybe<bool> V8TestCallbackInterface::booleanMethod(ScriptWrappable* callback_this_value) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return true; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "booleanMethod", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<bool>(); } // step 7. Prepare to run script with relevant settings. @@ -125,14 +151,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return true; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "booleanMethod", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<bool>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -146,7 +175,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "booleanMethod")) .ToLocal(&value)) { - return false; + return v8::Nothing<bool>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -158,7 +187,7 @@ "booleanMethod", "TestCallbackInterface", "The provided callback is not callable.")); - return false; + return v8::Nothing<bool>(); } } @@ -195,7 +224,7 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return false; + return v8::Nothing<bool>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to @@ -208,17 +237,31 @@ auto native_result = NativeValueTraits<IDLBoolean>::NativeValue( GetIsolate(), call_result, exception_state); - ALLOW_UNUSED_LOCAL(native_result); - return !exception_state.HadException(); + if (exception_state.HadException()) + return v8::Nothing<bool>(); + else + return v8::Just<bool>(native_result); } } -void V8TestCallbackInterface::voidMethodBooleanArg(ScriptWrappable* callback_this_value, bool boolArg) { +v8::Maybe<void> V8TestCallbackInterface::voidMethodBooleanArg(ScriptWrappable* callback_this_value, bool boolArg) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodBooleanArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -226,14 +269,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodBooleanArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -247,7 +293,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "voidMethodBooleanArg")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -259,7 +305,7 @@ "voidMethodBooleanArg", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -297,21 +343,32 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); } -void V8TestCallbackInterface::voidMethodSequenceArg(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceEmpty>>& sequenceArg) { +v8::Maybe<void> V8TestCallbackInterface::voidMethodSequenceArg(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceEmpty>>& sequenceArg) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodSequenceArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -319,14 +376,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodSequenceArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -340,7 +400,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "voidMethodSequenceArg")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -352,7 +412,7 @@ "voidMethodSequenceArg", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -390,21 +450,32 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); } -void V8TestCallbackInterface::voidMethodFloatArg(ScriptWrappable* callback_this_value, float floatArg) { +v8::Maybe<void> V8TestCallbackInterface::voidMethodFloatArg(ScriptWrappable* callback_this_value, float floatArg) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodFloatArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -412,14 +483,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodFloatArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -433,7 +507,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "voidMethodFloatArg")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -445,7 +519,7 @@ "voidMethodFloatArg", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -483,21 +557,32 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); } -void V8TestCallbackInterface::voidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) { +v8::Maybe<void> V8TestCallbackInterface::voidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodTestInterfaceEmptyArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -505,14 +590,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodTestInterfaceEmptyArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -526,7 +614,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "voidMethodTestInterfaceEmptyArg")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -538,7 +626,7 @@ "voidMethodTestInterfaceEmptyArg", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -576,21 +664,32 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); } -void V8TestCallbackInterface::voidMethodTestInterfaceEmptyStringArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg, const String& stringArg) { +v8::Maybe<void> V8TestCallbackInterface::voidMethodTestInterfaceEmptyStringArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg, const String& stringArg) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodTestInterfaceEmptyStringArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -598,14 +697,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "voidMethodTestInterfaceEmptyStringArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -619,7 +721,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "voidMethodTestInterfaceEmptyStringArg")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -631,7 +733,7 @@ "voidMethodTestInterfaceEmptyStringArg", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -670,21 +772,32 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); } -void V8TestCallbackInterface::callbackWithThisValueVoidMethodStringArg(ScriptWrappable* callback_this_value, const String& stringArg) { +v8::Maybe<void> V8TestCallbackInterface::callbackWithThisValueVoidMethodStringArg(ScriptWrappable* callback_this_value, const String& stringArg) { // This function implements "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { - return; + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "callbackWithThisValueVoidMethodStringArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } // step 7. Prepare to run script with relevant settings. @@ -692,14 +805,17 @@ CallbackRelevantScriptState()); // step 8. Prepare to run a callback with stored settings. if (IncumbentScriptState()->GetContext().IsEmpty()) { - return; + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "callbackWithThisValueVoidMethodStringArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); } v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); - v8::TryCatch try_catch(GetIsolate()); - try_catch.SetVerbose(true); - v8::Local<v8::Function> function; if (IsCallbackObjectCallable()) { // step 9.1. If value's interface is a single operation callback interface @@ -713,7 +829,7 @@ if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), V8String(GetIsolate(), "callbackWithThisValueVoidMethodStringArg")) .ToLocal(&value)) { - return; + return v8::Nothing<void>(); } // step 10. If !IsCallable(X) is false, then set completion to a new // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError @@ -725,7 +841,7 @@ "callbackWithThisValueVoidMethodStringArg", "TestCallbackInterface", "The provided callback is not callable.")); - return; + return v8::Nothing<void>(); } } @@ -763,13 +879,119 @@ GetIsolate()).ToLocal(&call_result)) { // step 14. If callResult is an abrupt completion, set completion to // callResult and jump to the step labeled return. - return; + return v8::Nothing<void>(); } // step 15. Set completion to the result of converting callResult.[[Value]] to // an IDL value of the same type as the operation's return type. - ALLOW_UNUSED_LOCAL(call_result); - return; + return v8::JustVoid(); +} + +v8::Maybe<void> V8TestCallbackInterface::customVoidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) { + // This function implements "call a user object's operation". + // https://heycam.github.io/webidl/#call-a-user-objects-operation + + if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) { + // Wrapper-tracing for the callback function makes the function object and + // its creation context alive. Thus it's safe to use the creation context + // of the callback function here. + v8::HandleScope handle_scope(GetIsolate()); + CHECK(!CallbackObject().IsEmpty()); + v8::Context::Scope context_scope(CallbackObject()->CreationContext()); + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "customVoidMethodTestInterfaceEmptyArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); + } + + // step 7. Prepare to run script with relevant settings. + ScriptState::Scope callback_relevant_context_scope( + CallbackRelevantScriptState()); + // step 8. Prepare to run a callback with stored settings. + if (IncumbentScriptState()->GetContext().IsEmpty()) { + V8ThrowException::ThrowError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "customVoidMethodTestInterfaceEmptyArg", + "TestCallbackInterface", + "The provided callback is no longer runnable.")); + return v8::Nothing<void>(); + } + v8::Context::BackupIncumbentScope backup_incumbent_scope( + IncumbentScriptState()->GetContext()); + + v8::Local<v8::Function> function; + if (IsCallbackObjectCallable()) { + // step 9.1. If value's interface is a single operation callback interface + // and !IsCallable(O) is true, then set X to O. + function = CallbackObject().As<v8::Function>(); + } else { + // step 9.2.1. Let getResult be Get(O, opName). + // step 9.2.2. If getResult is an abrupt completion, set completion to + // getResult and jump to the step labeled return. + v8::Local<v8::Value> value; + if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + V8String(GetIsolate(), "customVoidMethodTestInterfaceEmptyArg")) + .ToLocal(&value)) { + return v8::Nothing<void>(); + } + // step 10. If !IsCallable(X) is false, then set completion to a new + // Completion{[[Type]]: throw, [[Value]]: a newly created TypeError + // object, [[Target]]: empty}, and jump to the step labeled return. + if (!value->IsFunction()) { + V8ThrowException::ThrowTypeError( + GetIsolate(), + ExceptionMessages::FailedToExecute( + "customVoidMethodTestInterfaceEmptyArg", + "TestCallbackInterface", + "The provided callback is not callable.")); + return v8::Nothing<void>(); + } + } + + v8::Local<v8::Value> this_arg; + if (!IsCallbackObjectCallable()) { + // step 11. If value's interface is not a single operation callback + // interface, or if !IsCallable(O) is false, set thisArg to O (overriding + // the provided value). + this_arg = CallbackObject(); + } else if (!callback_this_value) { + // step 2. If thisArg was not given, let thisArg be undefined. + this_arg = v8::Undefined(GetIsolate()); + } else { + this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + } + + // step 12. Let esArgs be the result of converting args to an ECMAScript + // arguments list. If this throws an exception, set completion to the + // completion value representing the thrown exception and jump to the step + // labeled return. + v8::Local<v8::Object> argument_creation_context = + CallbackRelevantScriptState()->GetContext()->Global(); + ALLOW_UNUSED_LOCAL(argument_creation_context); + v8::Local<v8::Value> testInterfaceEmptyArgHandle = ToV8(testInterfaceEmptyArg, argument_creation_context, GetIsolate()); + v8::Local<v8::Value> argv[] = { testInterfaceEmptyArgHandle }; + + // step 13. Let callResult be Call(X, thisArg, esArgs). + v8::Local<v8::Value> call_result; + if (!V8ScriptRunner::CallFunction( + function, + ExecutionContext::From(CallbackRelevantScriptState()), + this_arg, + 1, + argv, + GetIsolate()).ToLocal(&call_result)) { + // step 14. If callResult is an abrupt completion, set completion to + // callResult and jump to the step labeled return. + return v8::Nothing<void>(); + } + + // step 15. Set completion to the result of converting callResult.[[Value]] to + // an IDL value of the same type as the operation's return type. + return v8::JustVoid(); } } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.h index d8914f8..f7299c97 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackInterface.h
@@ -29,39 +29,39 @@ // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void voidMethod(ScriptWrappable* callback_this_value); + v8::Maybe<void> voidMethod(ScriptWrappable* callback_this_value) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - bool booleanMethod(ScriptWrappable* callback_this_value); + v8::Maybe<bool> booleanMethod(ScriptWrappable* callback_this_value) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void voidMethodBooleanArg(ScriptWrappable* callback_this_value, bool boolArg); + v8::Maybe<void> voidMethodBooleanArg(ScriptWrappable* callback_this_value, bool boolArg) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void voidMethodSequenceArg(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceEmpty>>& sequenceArg); + v8::Maybe<void> voidMethodSequenceArg(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceEmpty>>& sequenceArg) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void voidMethodFloatArg(ScriptWrappable* callback_this_value, float floatArg); + v8::Maybe<void> voidMethodFloatArg(ScriptWrappable* callback_this_value, float floatArg) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void voidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg); + v8::Maybe<void> voidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void voidMethodTestInterfaceEmptyStringArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg, const String& stringArg); + v8::Maybe<void> voidMethodTestInterfaceEmptyStringArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg, const String& stringArg) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void callbackWithThisValueVoidMethodStringArg(ScriptWrappable* callback_this_value, const String& stringArg); + v8::Maybe<void> callbackWithThisValueVoidMethodStringArg(ScriptWrappable* callback_this_value, const String& stringArg) WARN_UNUSED_RESULT; // Performs "call a user object's operation". // https://heycam.github.io/webidl/#call-a-user-objects-operation - void customVoidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg); + v8::Maybe<void> customVoidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) WARN_UNUSED_RESULT; private: explicit V8TestCallbackInterface(v8::Local<v8::Object> callback_object)
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc index 2cace7aa..94d8090d 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc
@@ -108,4 +108,10 @@ } } +CORE_TEMPLATE_EXPORT +v8::Maybe<ScriptValue> V8PersistentCallbackFunction<V8AnyCallbackFunctionOptionalAnyArg>::Invoke(ScriptWrappable* callback_this_value, ScriptValue optionalAnyArg) { + return Proxy()->Invoke( + callback_this_value, optionalAnyArg); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.h index 9772ae4..112c88c 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class CORE_EXPORT V8AnyCallbackFunctionOptionalAnyArg : public CallbackFunctionBase { +class CORE_EXPORT V8AnyCallbackFunctionOptionalAnyArg final : public CallbackFunctionBase { public: static V8AnyCallbackFunctionOptionalAnyArg* Create(v8::Local<v8::Function> callback_function) { return new V8AnyCallbackFunctionOptionalAnyArg(callback_function); @@ -31,15 +31,44 @@ // https://heycam.github.io/webidl/#es-invoking-callback-functions v8::Maybe<ScriptValue> Invoke(ScriptWrappable* callback_this_value, ScriptValue optionalAnyArg) WARN_UNUSED_RESULT; - protected: - explicit V8AnyCallbackFunctionOptionalAnyArg(const V8AnyCallbackFunctionOptionalAnyArg& other) - : CallbackFunctionBase(other) {} - private: explicit V8AnyCallbackFunctionOptionalAnyArg(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8AnyCallbackFunctionOptionalAnyArg> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8AnyCallbackFunctionOptionalAnyArg; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<ScriptValue> Invoke(ScriptWrappable* callback_this_value, ScriptValue optionalAnyArg) WARN_UNUSED_RESULT; + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8AnyCallbackFunctionOptionalAnyArg is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8AnyCallbackFunctionOptionalAnyArg> WrapPersistent(V8AnyCallbackFunctionOptionalAnyArg*) = delete; + } // namespace blink #endif // V8AnyCallbackFunctionOptionalAnyArg_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc index 881268a..9df7a635 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.cc
@@ -111,4 +111,10 @@ } } +CORE_TEMPLATE_EXPORT +v8::Maybe<int32_t> V8PersistentCallbackFunction<V8LongCallbackFunction>::Invoke(ScriptWrappable* callback_this_value, int32_t num1, int32_t num2) { + return Proxy()->Invoke( + callback_this_value, num1, num2); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.h index e7b0a63..63372e6 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_long_callback_function.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class CORE_EXPORT V8LongCallbackFunction : public CallbackFunctionBase { +class CORE_EXPORT V8LongCallbackFunction final : public CallbackFunctionBase { public: static V8LongCallbackFunction* Create(v8::Local<v8::Function> callback_function) { return new V8LongCallbackFunction(callback_function); @@ -31,15 +31,44 @@ // https://heycam.github.io/webidl/#es-invoking-callback-functions v8::Maybe<int32_t> Invoke(ScriptWrappable* callback_this_value, int32_t num1, int32_t num2) WARN_UNUSED_RESULT; - protected: - explicit V8LongCallbackFunction(const V8LongCallbackFunction& other) - : CallbackFunctionBase(other) {} - private: explicit V8LongCallbackFunction(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8LongCallbackFunction> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8LongCallbackFunction; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<int32_t> Invoke(ScriptWrappable* callback_this_value, int32_t num1, int32_t num2) WARN_UNUSED_RESULT; + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8LongCallbackFunction is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8LongCallbackFunction> WrapPersistent(V8LongCallbackFunction*) = delete; + } // namespace blink #endif // V8LongCallbackFunction_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc index b52150f..204cf43 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc
@@ -110,4 +110,10 @@ } } +CORE_TEMPLATE_EXPORT +v8::Maybe<Vector<String>> V8PersistentCallbackFunction<V8StringSequenceCallbackFunctionLongSequenceArg>::Invoke(ScriptWrappable* callback_this_value, const Vector<int32_t>& arg) { + return Proxy()->Invoke( + callback_this_value, arg); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.h index 94ce68f..3ab58220 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class CORE_EXPORT V8StringSequenceCallbackFunctionLongSequenceArg : public CallbackFunctionBase { +class CORE_EXPORT V8StringSequenceCallbackFunctionLongSequenceArg final : public CallbackFunctionBase { public: static V8StringSequenceCallbackFunctionLongSequenceArg* Create(v8::Local<v8::Function> callback_function) { return new V8StringSequenceCallbackFunctionLongSequenceArg(callback_function); @@ -31,15 +31,44 @@ // https://heycam.github.io/webidl/#es-invoking-callback-functions v8::Maybe<Vector<String>> Invoke(ScriptWrappable* callback_this_value, const Vector<int32_t>& arg) WARN_UNUSED_RESULT; - protected: - explicit V8StringSequenceCallbackFunctionLongSequenceArg(const V8StringSequenceCallbackFunctionLongSequenceArg& other) - : CallbackFunctionBase(other) {} - private: explicit V8StringSequenceCallbackFunctionLongSequenceArg(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8StringSequenceCallbackFunctionLongSequenceArg> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8StringSequenceCallbackFunctionLongSequenceArg; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<Vector<String>> Invoke(ScriptWrappable* callback_this_value, const Vector<int32_t>& arg) WARN_UNUSED_RESULT; + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8StringSequenceCallbackFunctionLongSequenceArg is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8StringSequenceCallbackFunctionLongSequenceArg> WrapPersistent(V8StringSequenceCallbackFunctionLongSequenceArg*) = delete; + } // namespace blink #endif // V8StringSequenceCallbackFunctionLongSequenceArg_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc index 317cdba1..db5d528 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.cc
@@ -109,4 +109,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +CORE_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunction>::Invoke(ScriptWrappable* callback_this_value) { + return Proxy()->Invoke( + callback_this_value); +} + +CORE_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunction>::InvokeAndReportException(ScriptWrappable* callback_this_value) { + Proxy()->InvokeAndReportException( + callback_this_value); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.h index b0bc5ce..775076e 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class CORE_EXPORT V8VoidCallbackFunction : public CallbackFunctionBase { +class CORE_EXPORT V8VoidCallbackFunction final : public CallbackFunctionBase { public: static V8VoidCallbackFunction* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunction(callback_function); @@ -35,15 +35,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value); - protected: - explicit V8VoidCallbackFunction(const V8VoidCallbackFunction& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunction(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunction> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunction; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value) WARN_UNUSED_RESULT; + CORE_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunction is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunction> WrapPersistent(V8VoidCallbackFunction*) = delete; + } // namespace blink #endif // V8VoidCallbackFunction_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc index 15b89e8d..eecca4a4 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc
@@ -111,4 +111,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +CORE_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunctionDictionaryArg>::Invoke(ScriptWrappable* callback_this_value, const TestDictionary& arg) { + return Proxy()->Invoke( + callback_this_value, arg); +} + +CORE_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunctionDictionaryArg>::InvokeAndReportException(ScriptWrappable* callback_this_value, const TestDictionary& arg) { + Proxy()->InvokeAndReportException( + callback_this_value, arg); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.h index f7a0fd0c..2623825e7 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.h
@@ -20,7 +20,7 @@ class ScriptWrappable; class TestDictionary; -class CORE_EXPORT V8VoidCallbackFunctionDictionaryArg : public CallbackFunctionBase { +class CORE_EXPORT V8VoidCallbackFunctionDictionaryArg final : public CallbackFunctionBase { public: static V8VoidCallbackFunctionDictionaryArg* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunctionDictionaryArg(callback_function); @@ -36,15 +36,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value, const TestDictionary& arg); - protected: - explicit V8VoidCallbackFunctionDictionaryArg(const V8VoidCallbackFunctionDictionaryArg& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunctionDictionaryArg(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunctionDictionaryArg> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunctionDictionaryArg; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value, const TestDictionary& arg) WARN_UNUSED_RESULT; + CORE_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value, const TestDictionary& arg); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunctionDictionaryArg is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunctionDictionaryArg> WrapPersistent(V8VoidCallbackFunctionDictionaryArg*) = delete; + } // namespace blink #endif // V8VoidCallbackFunctionDictionaryArg_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc index 335c166..03de0d9b 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc
@@ -131,4 +131,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +CORE_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunctionEnumArg>::Invoke(ScriptWrappable* callback_this_value, const String& arg) { + return Proxy()->Invoke( + callback_this_value, arg); +} + +CORE_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunctionEnumArg>::InvokeAndReportException(ScriptWrappable* callback_this_value, const String& arg) { + Proxy()->InvokeAndReportException( + callback_this_value, arg); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.h index 9e073f09..9867c9f 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_enum_arg.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class CORE_EXPORT V8VoidCallbackFunctionEnumArg : public CallbackFunctionBase { +class CORE_EXPORT V8VoidCallbackFunctionEnumArg final : public CallbackFunctionBase { public: static V8VoidCallbackFunctionEnumArg* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunctionEnumArg(callback_function); @@ -35,15 +35,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value, const String& arg); - protected: - explicit V8VoidCallbackFunctionEnumArg(const V8VoidCallbackFunctionEnumArg& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunctionEnumArg(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunctionEnumArg> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunctionEnumArg; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value, const String& arg) WARN_UNUSED_RESULT; + CORE_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value, const String& arg); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunctionEnumArg is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunctionEnumArg> WrapPersistent(V8VoidCallbackFunctionEnumArg*) = delete; + } // namespace blink #endif // V8VoidCallbackFunctionEnumArg_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc index 6b450cb..70b9c5a 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc
@@ -111,4 +111,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +CORE_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunctionInterfaceArg>::Invoke(ScriptWrappable* callback_this_value, HTMLDivElement* divElement) { + return Proxy()->Invoke( + callback_this_value, divElement); +} + +CORE_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunctionInterfaceArg>::InvokeAndReportException(ScriptWrappable* callback_this_value, HTMLDivElement* divElement) { + Proxy()->InvokeAndReportException( + callback_this_value, divElement); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.h index e3231b2..b54b4ed5 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_interface_arg.h
@@ -20,7 +20,7 @@ class HTMLDivElement; class ScriptWrappable; -class CORE_EXPORT V8VoidCallbackFunctionInterfaceArg : public CallbackFunctionBase { +class CORE_EXPORT V8VoidCallbackFunctionInterfaceArg final : public CallbackFunctionBase { public: static V8VoidCallbackFunctionInterfaceArg* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunctionInterfaceArg(callback_function); @@ -36,15 +36,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value, HTMLDivElement* divElement); - protected: - explicit V8VoidCallbackFunctionInterfaceArg(const V8VoidCallbackFunctionInterfaceArg& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunctionInterfaceArg(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunctionInterfaceArg> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunctionInterfaceArg; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value, HTMLDivElement* divElement) WARN_UNUSED_RESULT; + CORE_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value, HTMLDivElement* divElement); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunctionInterfaceArg is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunctionInterfaceArg> WrapPersistent(V8VoidCallbackFunctionInterfaceArg*) = delete; + } // namespace blink #endif // V8VoidCallbackFunctionInterfaceArg_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc index 80a9f52..b1c23a1 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc
@@ -112,4 +112,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +CORE_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunctionTestInterfaceSequenceArg>::Invoke(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceImplementation>>& arg) { + return Proxy()->Invoke( + callback_this_value, arg); +} + +CORE_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunctionTestInterfaceSequenceArg>::InvokeAndReportException(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceImplementation>>& arg) { + Proxy()->InvokeAndReportException( + callback_this_value, arg); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.h index a1e90bc..1a82a9f 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.h
@@ -20,7 +20,7 @@ class ScriptWrappable; class TestInterfaceImplementation; -class CORE_EXPORT V8VoidCallbackFunctionTestInterfaceSequenceArg : public CallbackFunctionBase { +class CORE_EXPORT V8VoidCallbackFunctionTestInterfaceSequenceArg final : public CallbackFunctionBase { public: static V8VoidCallbackFunctionTestInterfaceSequenceArg* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunctionTestInterfaceSequenceArg(callback_function); @@ -36,15 +36,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceImplementation>>& arg); - protected: - explicit V8VoidCallbackFunctionTestInterfaceSequenceArg(const V8VoidCallbackFunctionTestInterfaceSequenceArg& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunctionTestInterfaceSequenceArg(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunctionTestInterfaceSequenceArg> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunctionTestInterfaceSequenceArg; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceImplementation>>& arg) WARN_UNUSED_RESULT; + CORE_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceImplementation>>& arg); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunctionTestInterfaceSequenceArg is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunctionTestInterfaceSequenceArg> WrapPersistent(V8VoidCallbackFunctionTestInterfaceSequenceArg*) = delete; + } // namespace blink #endif // V8VoidCallbackFunctionTestInterfaceSequenceArg_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc index 3235d68..87bedc6 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.cc
@@ -111,4 +111,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +CORE_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunctionTypedef>::Invoke(ScriptWrappable* callback_this_value, const String& arg) { + return Proxy()->Invoke( + callback_this_value, arg); +} + +CORE_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunctionTypedef>::InvokeAndReportException(ScriptWrappable* callback_this_value, const String& arg) { + Proxy()->InvokeAndReportException( + callback_this_value, arg); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.h b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.h index c3f690df..6405e433 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/v8_void_callback_function_typedef.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class CORE_EXPORT V8VoidCallbackFunctionTypedef : public CallbackFunctionBase { +class CORE_EXPORT V8VoidCallbackFunctionTypedef final : public CallbackFunctionBase { public: static V8VoidCallbackFunctionTypedef* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunctionTypedef(callback_function); @@ -35,15 +35,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value, const String& arg); - protected: - explicit V8VoidCallbackFunctionTypedef(const V8VoidCallbackFunctionTypedef& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunctionTypedef(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class CORE_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunctionTypedef> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunctionTypedef; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + CORE_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value, const String& arg) WARN_UNUSED_RESULT; + CORE_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value, const String& arg); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunctionTypedef is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunctionTypedef> WrapPersistent(V8VoidCallbackFunctionTypedef*) = delete; + } // namespace blink #endif // V8VoidCallbackFunctionTypedef_h
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc b/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc index 0edd594..5a2bb52 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc +++ b/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.cc
@@ -109,4 +109,16 @@ ALLOW_UNUSED_LOCAL(maybe_result); } +MODULES_TEMPLATE_EXPORT +v8::Maybe<void> V8PersistentCallbackFunction<V8VoidCallbackFunctionModules>::Invoke(ScriptWrappable* callback_this_value) { + return Proxy()->Invoke( + callback_this_value); +} + +MODULES_TEMPLATE_EXPORT +void V8PersistentCallbackFunction<V8VoidCallbackFunctionModules>::InvokeAndReportException(ScriptWrappable* callback_this_value) { + Proxy()->InvokeAndReportException( + callback_this_value); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.h b/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.h index 950e8944f..84f9c982 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.h +++ b/third_party/WebKit/Source/bindings/tests/results/modules/v8_void_callback_function_modules.h
@@ -19,7 +19,7 @@ class ScriptWrappable; -class MODULES_EXPORT V8VoidCallbackFunctionModules : public CallbackFunctionBase { +class MODULES_EXPORT V8VoidCallbackFunctionModules final : public CallbackFunctionBase { public: static V8VoidCallbackFunctionModules* Create(v8::Local<v8::Function> callback_function) { return new V8VoidCallbackFunctionModules(callback_function); @@ -35,15 +35,46 @@ // error handler such as DevTools' console. void InvokeAndReportException(ScriptWrappable* callback_this_value); - protected: - explicit V8VoidCallbackFunctionModules(const V8VoidCallbackFunctionModules& other) - : CallbackFunctionBase(other) {} - private: explicit V8VoidCallbackFunctionModules(v8::Local<v8::Function> callback_function) : CallbackFunctionBase(callback_function) {} }; +template <> +class MODULES_TEMPLATE_CLASS_EXPORT V8PersistentCallbackFunction<V8VoidCallbackFunctionModules> final : public V8PersistentCallbackFunctionBase { + using V8CallbackFunction = V8VoidCallbackFunctionModules; + + public: + ~V8PersistentCallbackFunction() override = default; + + // Returns a wrapper-tracing version of this callback function. + V8CallbackFunction* ToNonV8Persistent() { return Proxy(); } + + MODULES_EXTERN_TEMPLATE_EXPORT + v8::Maybe<void> Invoke(ScriptWrappable* callback_this_value) WARN_UNUSED_RESULT; + MODULES_EXTERN_TEMPLATE_EXPORT + void InvokeAndReportException(ScriptWrappable* callback_this_value); + + private: + explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) + : V8PersistentCallbackFunctionBase(callback_function) {} + + V8CallbackFunction* Proxy() { + return As<V8CallbackFunction>(); + } + + template <typename V8CallbackFunction> + friend V8PersistentCallbackFunction<V8CallbackFunction>* + ToV8PersistentCallbackFunction(V8CallbackFunction*); +}; + +// V8VoidCallbackFunctionModules is designed to be used with wrapper-tracing. +// As blink::Persistent does not perform wrapper-tracing, use of +// |WrapPersistent| for callback functions is likely (if not always) misuse. +// Thus, this code prohibits such a use case. The call sites should explicitly +// use WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<V8VoidCallbackFunctionModules> WrapPersistent(V8VoidCallbackFunctionModules*) = delete; + } // namespace blink #endif // V8VoidCallbackFunctionModules_h
diff --git a/third_party/WebKit/Source/core/CoreExport.h b/third_party/WebKit/Source/core/CoreExport.h index 0659a1fa..8541dbe 100644 --- a/third_party/WebKit/Source/core/CoreExport.h +++ b/third_party/WebKit/Source/core/CoreExport.h
@@ -2,48 +2,71 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// This header defines macros to export component's symbols. +// See "platform/PlatformExport.h" for details. + #ifndef CoreExport_h #define CoreExport_h #include "build/build_config.h" -#if defined(COMPONENT_BUILD) -#if defined(WIN32) +// +// BLINK_CORE_IMPLEMENTATION +// +#if !defined(BLINK_CORE_IMPLEMENTATION) +#define BLINK_CORE_IMPLEMENTATION 0 +#endif -#if defined(BLINK_CORE_IMPLEMENTATION) && BLINK_CORE_IMPLEMENTATION +// +// CORE_EXPORT +// +#if !defined(COMPONENT_BUILD) +#define CORE_EXPORT // No need of export +#else + +#if defined(COMPILER_MSVC) +#if BLINK_CORE_IMPLEMENTATION #define CORE_EXPORT __declspec(dllexport) #else #define CORE_EXPORT __declspec(dllimport) -#endif // defined(BLINK_CORE_IMPLEMENTATION) && BLINK_CORE_IMPLEMENTATION +#endif +#endif // defined(COMPILER_MSVC) -#else // defined(WIN32) -#if defined(BLINK_CORE_IMPLEMENTATION) && BLINK_CORE_IMPLEMENTATION +#if defined(COMPILER_GCC) +#if BLINK_CORE_IMPLEMENTATION #define CORE_EXPORT __attribute__((visibility("default"))) #else #define CORE_EXPORT #endif -#endif +#endif // defined(COMPILER_GCC) -#else // defined(COMPONENT_BUILD) -#define CORE_EXPORT -#endif +#endif // !defined(COMPONENT_BUILD) -#if defined(BLINK_CORE_IMPLEMENTATION) && BLINK_CORE_IMPLEMENTATION +// +// CORE_TEMPLATE_CLASS_EXPORT +// CORE_EXTERN_TEMPLATE_EXPORT +// CORE_TEMPLATE_EXPORT +// +#if BLINK_CORE_IMPLEMENTATION + #if defined(COMPILER_MSVC) #define CORE_TEMPLATE_CLASS_EXPORT #define CORE_EXTERN_TEMPLATE_EXPORT CORE_EXPORT #define CORE_TEMPLATE_EXPORT CORE_EXPORT -#elif defined(COMPILER_GCC) +#endif + +#if defined(COMPILER_GCC) #define CORE_TEMPLATE_CLASS_EXPORT CORE_EXPORT #define CORE_EXTERN_TEMPLATE_EXPORT CORE_EXPORT #define CORE_TEMPLATE_EXPORT -#else -#error Unknown compiler #endif -#else // !BLINK_CORE_IMPLEMENTATION + +#else // BLINK_CORE_IMPLEMENTATION + #define CORE_TEMPLATE_CLASS_EXPORT #define CORE_EXTERN_TEMPLATE_EXPORT CORE_EXPORT #define CORE_TEMPLATE_EXPORT -#endif + +#endif // BLINK_CORE_IMPLEMENTATION #endif // CoreExport_h
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp index 4f09d68..6fa726b 100644 --- a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp +++ b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp
@@ -32,7 +32,6 @@ #include "base/location.h" #include "bindings/core/v8/V8BindingForCore.h" -#include "bindings/core/v8/v8_function_string_callback.h" #include "core/clipboard/DataObjectItem.h" #include "core/clipboard/DataTransfer.h" #include "core/dom/ExecutionContext.h" @@ -76,14 +75,16 @@ if (!callback || item_->Kind() != DataObjectItem::kStringKind) return; - callbacks_.emplace_back(callback); + auto* v8persistent_callback = ToV8PersistentCallbackFunction(callback); ExecutionContext* context = ExecutionContext::From(script_state); - probe::AsyncTaskScheduled(context, "DataTransferItem.getAsString", callback); + probe::AsyncTaskScheduled(context, "DataTransferItem.getAsString", + v8persistent_callback); context->GetTaskRunner(TaskType::kUserInteraction) ->PostTask(FROM_HERE, WTF::Bind(&DataTransferItem::RunGetAsStringTask, WrapPersistent(this), WrapPersistent(context), - WrapPersistent(callback), item_->GetAsString())); + WrapPersistent(v8persistent_callback), + item_->GetAsString())); } File* DataTransferItem::getAsFile() const { @@ -97,30 +98,20 @@ DataObjectItem* item) : data_transfer_(data_transfer), item_(item) {} -void DataTransferItem::RunGetAsStringTask(ExecutionContext* context, - V8FunctionStringCallback* callback, - const String& data) { +void DataTransferItem::RunGetAsStringTask( + ExecutionContext* context, + V8PersistentCallbackFunction<V8FunctionStringCallback>* callback, + const String& data) { DCHECK(callback); probe::AsyncTask async_task(context, callback); if (context) callback->InvokeAndReportException(nullptr, data); - size_t index = callbacks_.Find(callback); - DCHECK(index != kNotFound); - callbacks_.EraseAt(index); } void DataTransferItem::Trace(blink::Visitor* visitor) { visitor->Trace(data_transfer_); visitor->Trace(item_); - visitor->Trace(callbacks_); ScriptWrappable::Trace(visitor); } -void DataTransferItem::TraceWrappers( - const ScriptWrappableVisitor* visitor) const { - for (auto callback : callbacks_) - visitor->TraceWrappers(callback); - ScriptWrappable::TraceWrappers(visitor); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferItem.h b/third_party/WebKit/Source/core/clipboard/DataTransferItem.h index c45673d8..7954e666 100644 --- a/third_party/WebKit/Source/core/clipboard/DataTransferItem.h +++ b/third_party/WebKit/Source/core/clipboard/DataTransferItem.h
@@ -32,9 +32,9 @@ #define DataTransferItem_h #include "base/macros.h" +#include "bindings/core/v8/v8_function_string_callback.h" #include "core/CoreExport.h" #include "platform/bindings/ScriptWrappable.h" -#include "platform/bindings/TraceWrapperMember.h" #include "platform/heap/Handle.h" #include "platform/wtf/Forward.h" @@ -45,7 +45,6 @@ class ExecutionContext; class File; class ScriptState; -class V8FunctionStringCallback; class CORE_EXPORT DataTransferItem final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); @@ -62,19 +61,18 @@ DataTransfer* GetDataTransfer() { return data_transfer_.Get(); } DataObjectItem* GetDataObjectItem() { return item_.Get(); } - void Trace(blink::Visitor*); - virtual void TraceWrappers(const ScriptWrappableVisitor*) const; + void Trace(blink::Visitor*) override; private: DataTransferItem(DataTransfer*, DataObjectItem*); - void RunGetAsStringTask(ExecutionContext*, - V8FunctionStringCallback*, - const String& data); + void RunGetAsStringTask( + ExecutionContext*, + V8PersistentCallbackFunction<V8FunctionStringCallback>*, + const String& data); Member<DataTransfer> data_transfer_; Member<DataObjectItem> item_; - HeapVector<TraceWrapperMember<V8FunctionStringCallback>> callbacks_; DISALLOW_COPY_AND_ASSIGN(DataTransferItem); };
diff --git a/third_party/WebKit/Source/core/css/CSSUnsetValue.cpp b/third_party/WebKit/Source/core/css/CSSUnsetValue.cpp index 74c96f4..b5367f2 100644 --- a/third_party/WebKit/Source/core/css/CSSUnsetValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSUnsetValue.cpp
@@ -8,6 +8,7 @@ #include "platform/wtf/text/WTFString.h" namespace blink { +namespace cssvalue { CSSUnsetValue* CSSUnsetValue::Create() { return CssValuePool().UnsetValue(); @@ -17,4 +18,5 @@ return "unset"; } +} // namespace cssvalue } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSUnsetValue.h b/third_party/WebKit/Source/core/css/CSSUnsetValue.h index 34b2139..bfe1597 100644 --- a/third_party/WebKit/Source/core/css/CSSUnsetValue.h +++ b/third_party/WebKit/Source/core/css/CSSUnsetValue.h
@@ -10,6 +10,10 @@ namespace blink { +class CSSValuePool; + +namespace cssvalue { + class CSSUnsetValue : public CSSValue { public: static CSSUnsetValue* Create(); @@ -23,13 +27,14 @@ } private: - friend class CSSValuePool; + friend class ::blink::CSSValuePool; CSSUnsetValue() : CSSValue(kUnsetClass) {} }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSUnsetValue, IsUnsetValue()); +} // namespace cssvalue } // namespace blink #endif // CSSUnsetValue_h
diff --git a/third_party/WebKit/Source/core/css/CSSValuePool.h b/third_party/WebKit/Source/core/css/CSSValuePool.h index 07923cb..bd4473e 100644 --- a/third_party/WebKit/Source/core/css/CSSValuePool.h +++ b/third_party/WebKit/Source/core/css/CSSValuePool.h
@@ -52,6 +52,7 @@ // TODO(sashab): Make all the value pools store const CSSValues. static const int kMaximumCacheableIntegerValue = 255; using CSSColorValue = cssvalue::CSSColorValue; + using CSSUnsetValue = cssvalue::CSSUnsetValue; using ColorValueCache = HeapHashMap<unsigned, Member<CSSColorValue>>; static const unsigned kMaximumColorCacheSize = 512; using FontFaceValueCache =
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp index 23436b60..e8b806d 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSKeywordValue.cpp
@@ -80,7 +80,7 @@ case (CSSValueInitial): return CSSInitialValue::Create(); case (CSSValueUnset): - return CSSUnsetValue::Create(); + return cssvalue::CSSUnsetValue::Create(); case (CSSValueInvalid): return CSSCustomIdentValue::Create(AtomicString(keyword_value_)); default:
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp index 3560183..2e4978b 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
@@ -1052,7 +1052,7 @@ if (value_id == CSSValueInitial) return CSSInitialValue::Create(); if (value_id == CSSValueUnset) - return CSSUnsetValue::Create(); + return cssvalue::CSSUnsetValue::Create(); if (CSSParserFastPaths::IsValidKeywordPropertyAndValue(property_id, value_id, parser_mode)) return CSSIdentifierValue::Create(value_id);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index addf207..d013b27 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -218,7 +218,7 @@ else if (id == CSSValueInherit) value = CSSInheritedValue::Create(); else if (id == CSSValueUnset) - value = CSSUnsetValue::Create(); + value = cssvalue::CSSUnsetValue::Create(); else return false;
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp index 468b0ce6..c22cfb5d 100644 --- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -219,12 +219,12 @@ if (!ResolveTokenRange(value.VariableDataValue()->Tokens(), disallow_animation_tainted, tokens, backing_strings, is_animation_tainted)) { - return CSSUnsetValue::Create(); + return cssvalue::CSSUnsetValue::Create(); } const CSSValue* result = CSSPropertyParser::ParseSingleValue(id, tokens, value.ParserContext()); if (!result) - return CSSUnsetValue::Create(); + return cssvalue::CSSUnsetValue::Create(); return result; } @@ -268,7 +268,7 @@ if (value) return value; - return CSSUnsetValue::Create(); + return cssvalue::CSSUnsetValue::Create(); } scoped_refptr<CSSVariableData>
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp index fba1b3d9..3526c30 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -54,6 +54,7 @@ #include "core/frame/UseCounter.h" #include "core/html/HTMLBRElement.h" #include "core/html/HTMLDivElement.h" +#include "core/html/HTMLImageElement.h" #include "core/html/HTMLLIElement.h" #include "core/html/HTMLParagraphElement.h" #include "core/html/HTMLSpanElement.h" @@ -963,14 +964,6 @@ !node->GetLayoutObject()->IsRubyText(); } -bool IsInline(const Node* node) { - if (!node) - return false; - - const ComputedStyle* style = node->GetComputedStyle(); - return style && style->Display() == EDisplay::kInline; -} - // TODO(yosin) Deploy this in all of the places where |enclosingBlockFlow()| and // |enclosingBlockFlowOrTableElement()| are used. // TODO(yosin) Callers of |Node| version of |enclosingBlock()| should use @@ -1690,32 +1683,6 @@ return target->DispatchEvent(before_input_event); } -InputEvent::InputType DeletionInputTypeFromTextGranularity( - DeleteDirection direction, - TextGranularity granularity) { - using InputType = InputEvent::InputType; - switch (direction) { - case DeleteDirection::kForward: - if (granularity == TextGranularity::kWord) - return InputType::kDeleteWordForward; - if (granularity == TextGranularity::kLineBoundary) - return InputType::kDeleteSoftLineForward; - if (granularity == TextGranularity::kParagraphBoundary) - return InputType::kDeleteHardLineForward; - return InputType::kDeleteContentForward; - case DeleteDirection::kBackward: - if (granularity == TextGranularity::kWord) - return InputType::kDeleteWordBackward; - if (granularity == TextGranularity::kLineBoundary) - return InputType::kDeleteSoftLineBackward; - if (granularity == TextGranularity::kParagraphBoundary) - return InputType::kDeleteHardLineBackward; - return InputType::kDeleteContentBackward; - default: - return InputType::kNone; - } -} - // |IsEmptyNonEditableNodeInEditable()| is introduced for fixing // http://crbug.com/428986. static bool IsEmptyNonEditableNodeInEditable(const Node& node) { @@ -1809,4 +1776,17 @@ return target; } +HTMLImageElement* ImageElementFromImageDocument(const Document* document) { + if (!document) + return nullptr; + if (!document->IsImageDocument()) + return nullptr; + + const HTMLElement* const body = document->body(); + if (!body) + return nullptr; + + return ToHTMLImageElementOrNull(body->firstChild()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h index 3b2a9f5..3e8223a 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.h +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -29,7 +29,6 @@ #include "core/CoreExport.h" #include "core/editing/EditingBoundary.h" #include "core/editing/Forward.h" -#include "core/editing/TextGranularity.h" #include "core/events/InputEvent.h" #include "platform/text/TextDirection.h" #include "platform/wtf/Forward.h" @@ -50,11 +49,6 @@ kGraphemeCluster, }; -enum class DeleteDirection { - kForward, - kBackward, -}; - class Document; class Element; class HTMLElement; @@ -165,7 +159,6 @@ // Returns true if the specified node is visible <table>. We don't want to add // invalid nodes to <table> elements. bool IsDisplayInsideTable(const Node*); -bool IsInline(const Node*); bool IsTableCell(const Node*); bool IsEmptyTableCell(const Node*); bool IsHTMLListElement(const Node*); @@ -325,6 +318,10 @@ Element* FindEventTargetFrom(LocalFrame&, const VisibleSelection&); +// Note: ImageElementFromImageDocument() is both used in ExecuteCopy() and +// Editor::CanCopy() +HTMLImageElement* ImageElementFromImageDocument(const Document*); + // Boolean functions on Element CORE_EXPORT bool ElementCannotHaveEndTag(const Node&); @@ -390,10 +387,6 @@ DispatchEventResult DispatchBeforeInputDataTransfer(Node*, InputEvent::InputType, DataTransfer*); - -InputEvent::InputType DeletionInputTypeFromTextGranularity(DeleteDirection, - TextGranularity); - } // namespace blink #endif
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index 920b1f59..6698da2 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -268,19 +268,6 @@ return CanCopy() && CanDelete(); } -static HTMLImageElement* ImageElementFromImageDocument(Document* document) { - if (!document) - return nullptr; - if (!document->IsImageDocument()) - return nullptr; - - HTMLElement* body = document->body(); - if (!body) - return nullptr; - - return ToHTMLImageElementOrNull(body->firstChild()); -} - bool Editor::CanCopy() const { if (ImageElementFromImageDocument(GetFrame().GetDocument())) return true; @@ -342,38 +329,6 @@ ->Apply(); } -bool Editor::DispatchCopyEvent(EditorCommandSource source) { - // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets - // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); - if (IsInPasswordField( - GetFrameSelection().ComputeVisibleSelectionInDOMTree().Start())) - return true; - - return DispatchClipboardEvent(EventTypeNames::copy, kDataTransferWritable, - source); -} - -bool Editor::DispatchCutEvent(EditorCommandSource source) { - // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets - // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); - if (IsInPasswordField( - GetFrameSelection().ComputeVisibleSelectionInDOMTree().Start())) - return true; - - return DispatchClipboardEvent(EventTypeNames::cut, kDataTransferWritable, - source); -} - -void Editor::WriteSelectionToPasteboard() { - KURL url = GetFrame().GetDocument()->Url(); - String html = GetFrameSelection().SelectedHTMLForClipboard(); - String plain_text = GetFrame().SelectedTextForClipboard(); - Pasteboard::GeneralPasteboard()->WriteHTML(html, url, plain_text, - CanSmartCopyOrDelete()); -} - bool Editor::DispatchClipboardEvent(const AtomicString& event_type, DataTransferAccessPolicy policy, EditorCommandSource source, @@ -519,18 +474,6 @@ .ToNormalizedEphemeralRange(); } -bool Editor::CanDeleteRange(const EphemeralRange& range) const { - if (range.IsCollapsed()) - return false; - - Node* start_container = range.StartPosition().ComputeContainerNode(); - Node* end_container = range.EndPosition().ComputeContainerNode(); - if (!start_container || !end_container) - return false; - - return HasEditableStyle(*start_container) && HasEditableStyle(*end_container); -} - void Editor::RespondToChangedContents(const Position& position) { if (GetFrame().GetSettings() && GetFrame().GetSettings()->GetAccessibilityEnabled()) { @@ -811,88 +754,6 @@ return true; } -void Editor::Cut(EditorCommandSource source) { - if (!DispatchCutEvent(source)) - return; - if (!CanCut()) - return; - - // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets - // needs to be audited. See http://crbug.com/590369 for more details. - // A 'cut' event handler might have dirtied the layout so we need to update - // before we obtain the selection. - GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); - - if (source == kCommandFromMenuOrKeyBinding && - !GetFrameSelection().SelectionHasFocus()) - return; - - // TODO(yosin) We should use early return style here. - if (CanDeleteRange(SelectedRange())) { - if (EnclosingTextControl(GetFrame() - .Selection() - .ComputeVisibleSelectionInDOMTree() - .Start())) { - String plain_text = GetFrame().SelectedTextForClipboard(); - Pasteboard::GeneralPasteboard()->WritePlainText( - plain_text, CanSmartCopyOrDelete() ? Pasteboard::kCanSmartReplace - : Pasteboard::kCannotSmartReplace); - } else { - WriteSelectionToPasteboard(); - } - - if (source == kCommandFromMenuOrKeyBinding) { - if (DispatchBeforeInputDataTransfer( - FindEventTargetForClipboardEvent(source), - InputEvent::InputType::kDeleteByCut, - nullptr) != DispatchEventResult::kNotCanceled) - return; - // 'beforeinput' event handler may destroy target frame. - if (frame_->GetDocument()->GetFrame() != frame_) - return; - } - DeleteSelectionWithSmartDelete( - CanSmartCopyOrDelete() ? DeleteMode::kSmart : DeleteMode::kSimple, - InputEvent::InputType::kDeleteByCut); - } -} - -void Editor::Copy(EditorCommandSource source) { - if (!DispatchCopyEvent(source)) - return; - if (!CanCopy()) - return; - - // Since copy is a read-only operation it succeeds anytime a selection - // is *visible*. In contrast to cut or paste, the selection does not - // need to be focused - being visible is enough. - if (source == kCommandFromMenuOrKeyBinding && GetFrameSelection().IsHidden()) - return; - - // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets - // needs to be audited. See http://crbug.com/590369 for more details. - // A 'copy' event handler might have dirtied the layout so we need to update - // before we obtain the selection. - GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); - - if (EnclosingTextControl( - GetFrameSelection().ComputeVisibleSelectionInDOMTree().Start())) { - Pasteboard::GeneralPasteboard()->WritePlainText( - GetFrame().SelectedTextForClipboard(), - CanSmartCopyOrDelete() ? Pasteboard::kCanSmartReplace - : Pasteboard::kCannotSmartReplace); - } else { - Document* document = GetFrame().GetDocument(); - if (HTMLImageElement* image_element = - ImageElementFromImageDocument(document)) { - WriteImageNodeToPasteboard(Pasteboard::GeneralPasteboard(), - *image_element, document->title()); - } else { - WriteSelectionToPasteboard(); - } - } -} - static void CountEditingEvent(ExecutionContext* execution_context, const Event* event, WebFeature feature_on_input,
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h index 1d114a3..0ae4602 100644 --- a/third_party/WebKit/Source/core/editing/Editor.h +++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -88,9 +88,6 @@ bool CanDelete() const; bool CanSmartCopyOrDelete() const; - void Cut(EditorCommandSource); - void Copy(EditorCommandSource); - static void CountEvent(ExecutionContext*, const Event*); void CopyImage(const HitTestResult&); @@ -305,14 +302,6 @@ return *frame_; } - bool CanDeleteRange(const EphemeralRange&) const; - - // Returns true if Editor should continue with default processing. - bool DispatchCopyEvent(EditorCommandSource); - bool DispatchCutEvent(EditorCommandSource); - - void WriteSelectionToPasteboard(); - void ChangeSelectionAfterCommand(const SelectionInDOMTree&, const SetSelectionOptions&);
diff --git a/third_party/WebKit/Source/core/editing/EditorTest.cpp b/third_party/WebKit/Source/core/editing/EditorTest.cpp index f189c7e0..24d4fdd 100644 --- a/third_party/WebKit/Source/core/editing/EditorTest.cpp +++ b/third_party/WebKit/Source/core/editing/EditorTest.cpp
@@ -50,7 +50,7 @@ checkbox.focus(); Editor& editor = GetDocument().GetFrame()->GetEditor(); - editor.Copy(kCommandFromMenuOrKeyBinding); + editor.CreateCommand("Copy").Execute(); const String copied = Pasteboard::GeneralPasteboard()->PlainText(); EXPECT_TRUE(copied.IsEmpty()) << copied << " was copied.";
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp index e48a837..e9de5fc 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp
@@ -29,6 +29,7 @@ #include "core/editing/commands/EditingCommandsUtilities.h" +#include "core/dom/NodeComputedStyle.h" #include "core/editing/EditingUtilities.h" #include "core/editing/SelectionTemplate.h" #include "core/editing/VisiblePosition.h" @@ -91,6 +92,14 @@ return layout_object->Style()->Visibility() == EVisibility::kVisible; } +bool IsInline(const Node* node) { + if (!node) + return false; + + const ComputedStyle* style = node->GetComputedStyle(); + return style && style->Display() == EDisplay::kInline; +} + // FIXME: This method should not need to call // isStartOfParagraph/isEndOfParagraph Node* EnclosingEmptyListItem(const VisiblePosition& visible_pos) { @@ -535,4 +544,30 @@ // TODO(tkent): Should we check and move Text node children of <html>? } +InputEvent::InputType DeletionInputTypeFromTextGranularity( + DeleteDirection direction, + TextGranularity granularity) { + using InputType = InputEvent::InputType; + switch (direction) { + case DeleteDirection::kForward: + if (granularity == TextGranularity::kWord) + return InputType::kDeleteWordForward; + if (granularity == TextGranularity::kLineBoundary) + return InputType::kDeleteSoftLineForward; + if (granularity == TextGranularity::kParagraphBoundary) + return InputType::kDeleteHardLineForward; + return InputType::kDeleteContentForward; + case DeleteDirection::kBackward: + if (granularity == TextGranularity::kWord) + return InputType::kDeleteWordBackward; + if (granularity == TextGranularity::kLineBoundary) + return InputType::kDeleteSoftLineBackward; + if (granularity == TextGranularity::kParagraphBoundary) + return InputType::kDeleteHardLineBackward; + return InputType::kDeleteContentBackward; + default: + return InputType::kNone; + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h index 24a632a..ba67bed6 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h +++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h
@@ -32,11 +32,18 @@ #include "core/CoreExport.h" #include "core/editing/Forward.h" +#include "core/editing/TextGranularity.h" +#include "core/events/InputEvent.h" #include "platform/wtf/text/CharacterNames.h" #include "platform/wtf/text/WTFString.h" namespace blink { +enum class DeleteDirection { + kForward, + kBackward, +}; + class Document; class Element; class HTMLElement; @@ -54,6 +61,7 @@ bool IsTableStructureNode(const Node*); bool IsNodeRendered(const Node&); +bool IsInline(const Node*); // Returns true if specified nodes are elements, have identical tag names, // have identical attributes, and are editable. CORE_EXPORT bool AreIdenticalElements(const Node&, const Node&); @@ -123,6 +131,9 @@ const String& NonBreakingSpaceString(); CORE_EXPORT void TidyUpHTMLStructure(Document&); + +InputEvent::InputType DeletionInputTypeFromTextGranularity(DeleteDirection, + TextGranularity); } // namespace blink #endif
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index 081d29b8..05b9dcd8 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -49,6 +49,7 @@ #include "core/editing/VisiblePosition.h" #include "core/editing/commands/ApplyStyleCommand.h" #include "core/editing/commands/CreateLinkCommand.h" +#include "core/editing/commands/EditingCommandsUtilities.h" #include "core/editing/commands/EditorCommandNames.h" #include "core/editing/commands/FormatBlockCommand.h" #include "core/editing/commands/IndentOutdentCommand.h" @@ -748,6 +749,29 @@ return frame.GetContentSettingsClient()->AllowWriteToClipboard(default_value); } +// Returns true if Editor should continue with default processing. +static bool DispatchCopyOrCutEvent(LocalFrame& frame, + EditorCommandSource source, + const AtomicString& event_type) { + // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. See http://crbug.com/590369 for more details. + frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); + if (IsInPasswordField( + frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) + return true; + + return frame.GetEditor().DispatchClipboardEvent( + event_type, kDataTransferWritable, source); +} + +static void WriteSelectionToPasteboard(LocalFrame& frame) { + const KURL& url = frame.GetDocument()->Url(); + const String html = frame.Selection().SelectedHTMLForClipboard(); + const String plain_text = frame.SelectedTextForClipboard(); + Pasteboard::GeneralPasteboard()->WriteHTML( + html, url, plain_text, frame.GetEditor().CanSmartCopyOrDelete()); +} + static bool ExecuteCopy(LocalFrame& frame, Event*, EditorCommandSource source, @@ -759,7 +783,40 @@ // |canExecute()|. See also "Cut", and "Paste" command. if (!CanWriteClipboard(frame, source)) return false; - frame.GetEditor().Copy(source); + if (!DispatchCopyOrCutEvent(frame, source, EventTypeNames::copy)) + return true; + if (!frame.GetEditor().CanCopy()) + return true; + + // Since copy is a read-only operation it succeeds anytime a selection + // is *visible*. In contrast to cut or paste, the selection does not + // need to be focused - being visible is enough. + if (source == kCommandFromMenuOrKeyBinding && frame.Selection().IsHidden()) + return true; + + // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. See http://crbug.com/590369 for more details. + // A 'copy' event handler might have dirtied the layout so we need to update + // before we obtain the selection. + frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); + + if (EnclosingTextControl( + frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) { + Pasteboard::GeneralPasteboard()->WritePlainText( + frame.SelectedTextForClipboard(), + frame.GetEditor().CanSmartCopyOrDelete() + ? Pasteboard::kCanSmartReplace + : Pasteboard::kCannotSmartReplace); + return true; + } + const Document* const document = frame.GetDocument(); + if (HTMLImageElement* image_element = + ImageElementFromImageDocument(document)) { + WriteImageNodeToPasteboard(Pasteboard::GeneralPasteboard(), *image_element, + document->title()); + return true; + } + WriteSelectionToPasteboard(frame); return true; } @@ -773,6 +830,19 @@ return CreateLinkCommand::Create(*frame.GetDocument(), value)->Apply(); } +static bool CanDeleteRange(const EphemeralRange& range) { + if (range.IsCollapsed()) + return false; + + const Node* const start_container = + range.StartPosition().ComputeContainerNode(); + const Node* const end_container = range.EndPosition().ComputeContainerNode(); + if (!start_container || !end_container) + return false; + + return HasEditableStyle(*start_container) && HasEditableStyle(*end_container); +} + static bool ExecuteCut(LocalFrame& frame, Event*, EditorCommandSource source, @@ -784,7 +854,49 @@ // |canExecute()|. See also "Copy", and "Paste" command. if (!CanWriteClipboard(frame, source)) return false; - frame.GetEditor().Cut(source); + if (!DispatchCopyOrCutEvent(frame, source, EventTypeNames::cut)) + return true; + if (!frame.GetEditor().CanCut()) + return true; + + // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. See http://crbug.com/590369 for more details. + // A 'cut' event handler might have dirtied the layout so we need to update + // before we obtain the selection. + frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); + + if (source == kCommandFromMenuOrKeyBinding && + !frame.Selection().SelectionHasFocus()) + return true; + + if (!CanDeleteRange(frame.GetEditor().SelectedRange())) + return true; + if (EnclosingTextControl( + frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) { + const String plain_text = frame.SelectedTextForClipboard(); + Pasteboard::GeneralPasteboard()->WritePlainText( + plain_text, frame.GetEditor().CanSmartCopyOrDelete() + ? Pasteboard::kCanSmartReplace + : Pasteboard::kCannotSmartReplace); + } else { + WriteSelectionToPasteboard(frame); + } + + if (source == kCommandFromMenuOrKeyBinding) { + if (DispatchBeforeInputDataTransfer( + frame.GetEditor().FindEventTargetForClipboardEvent(source), + InputEvent::InputType::kDeleteByCut, + nullptr) != DispatchEventResult::kNotCanceled) + return true; + // 'beforeinput' event handler may destroy target frame. + if (frame.GetDocument()->GetFrame() != frame) + return true; + } + frame.GetEditor().DeleteSelectionWithSmartDelete( + frame.GetEditor().CanSmartCopyOrDelete() ? DeleteMode::kSmart + : DeleteMode::kSimple, + InputEvent::InputType::kDeleteByCut); + return true; } @@ -2526,22 +2638,10 @@ // because we allow elements that are not normally selectable to implement // copy/paste (like divs, or a document body). -static bool CanDHTMLCopyOrCut(LocalFrame& frame, - EditorCommandSource source, - const AtomicString& event_type) { - // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets - // needs to be audited. See http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); - return !IsInPasswordField( - frame.Selection().ComputeVisibleSelectionInDOMTree().Start()) && - !frame.GetEditor().DispatchClipboardEvent(event_type, - kDataTransferNumb, source); -} - static bool EnabledCopy(LocalFrame& frame, Event*, EditorCommandSource source) { if (!CanWriteClipboard(frame, source)) return false; - return CanDHTMLCopyOrCut(frame, source, EventTypeNames::beforecopy) || + return !DispatchCopyOrCutEvent(frame, source, EventTypeNames::beforecopy) || frame.GetEditor().CanCopy(); } @@ -2551,7 +2651,7 @@ if (source == kCommandFromMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) return false; - return CanDHTMLCopyOrCut(frame, source, EventTypeNames::beforecut) || + return !DispatchCopyOrCutEvent(frame, source, EventTypeNames::beforecut) || frame.GetEditor().CanCut(); }
diff --git a/third_party/WebKit/Source/core/events/event_type_names.json5 b/third_party/WebKit/Source/core/events/event_type_names.json5 index 276c0a1..74eb74c 100644 --- a/third_party/WebKit/Source/core/events/event_type_names.json5 +++ b/third_party/WebKit/Source/core/events/event_type_names.json5
@@ -203,7 +203,7 @@ "pointerup", "popstate", "progress", - "processorstatechange", + "processorerror", "push", "ratechange", "reading",
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp index 5a17502..8553af6 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -715,7 +715,8 @@ web_frame_->Client()->DidRunContentWithCertificateErrors(); } -void LocalFrameClientImpl::ReportLegacySymantecCert(const KURL& url) { +void LocalFrameClientImpl::ReportLegacySymantecCert(const KURL& url, + bool did_fail) { // To prevent log spam, only log the message once per hostname. if (certificate_warning_hosts_.Contains(url.Host())) return; @@ -733,35 +734,60 @@ WebString console_message; if (num_certificate_warning_messages_ == kMaxCertificateWarningMessages) { - console_message = - WebString(String("Additional resources on this page were loaded with " - "SSL certificates that will be " - "distrusted in the future. " - "Once distrusted, users will be prevented from " - "loading these resources. See " - "https://g.co/chrome/symantecpkicerts for " - "more information.")); - } else if (!web_frame_->Client()->OverrideLegacySymantecCertConsoleMessage( - url, &console_message)) { - console_message = WebString( - String::Format("The SSL certificate used to load resources from %s" - " will be " - "distrusted in the future. " - "Once distrusted, users will be prevented from " - "loading these resources. See " - "https://g.co/chrome/symantecpkicerts for " - "more information.", - SecurityOrigin::Create(url)->ToString().Utf8().data())); + if (did_fail) { + console_message = + WebString(String("Additional resources on this page were loaded with " + "SSL certificates that have been " + "distrusted. See " + "https://g.co/chrome/symantecpkicerts for " + "more information.")); + } else { + console_message = + WebString(String("Additional resources on this page were loaded with " + "SSL certificates that will be " + "distrusted in the future. " + "Once distrusted, users will be prevented from " + "loading these resources. See " + "https://g.co/chrome/symantecpkicerts for " + "more information.")); + } + } else { + // The embedder is given a chance to override the message for certs that + // will be distrusted in future, but not for certs that have already been + // distrusted. (This is because there is no embedder-specific release + // information in the message for certs that have already been distrusted.) + if (did_fail) { + console_message = WebString(String::Format( + "The SSL certificate used to load resources from %s" + " has been distrusted. See " + "https://g.co/chrome/symantecpkicerts for " + "more information.", + SecurityOrigin::Create(url)->ToString().Utf8().data())); + } else if (!web_frame_->Client()->OverrideLegacySymantecCertConsoleMessage( + url, &console_message)) { + console_message = WebString(String::Format( + "The SSL certificate used to load resources from %s" + " will be " + "distrusted in the future. " + "Once distrusted, users will be prevented from " + "loading these resources. See " + "https://g.co/chrome/symantecpkicerts for " + "more information.", + SecurityOrigin::Create(url)->ToString().Utf8().data())); + } } num_certificate_warning_messages_++; certificate_warning_hosts_.insert(url.Host()); // To avoid spamming the console, use Verbose message level for subframe - // resources and only use the warning level for main-frame resources. + // resources for certificates that will be distrusted in future, and only use + // the warning level for main-frame resources or resources that have already + // been distrusted. web_frame_->GetFrame()->GetDocument()->AddConsoleMessage( - ConsoleMessage::Create( - kSecurityMessageSource, - web_frame_->Parent() ? kVerboseMessageLevel : kWarningMessageLevel, - console_message)); + ConsoleMessage::Create(kSecurityMessageSource, + (web_frame_->Parent() && !did_fail) + ? kVerboseMessageLevel + : kWarningMessageLevel, + console_message)); } void LocalFrameClientImpl::DidChangePerformanceTiming() {
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h index 3ca4f8e..897fda8 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
@@ -142,7 +142,7 @@ void DidDispatchPingLoader(const KURL&) override; void DidDisplayContentWithCertificateErrors() override; void DidRunContentWithCertificateErrors() override; - void ReportLegacySymantecCert(const KURL&) override; + void ReportLegacySymantecCert(const KURL&, bool) override; void DidChangePerformanceTiming() override; void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) override; void DidObserveNewFeatureUsage(mojom::WebFeature) override;
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h index 3510d2a..146a026 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -190,10 +190,12 @@ // The frame ran content with certificate errors with the given URL. virtual void DidRunContentWithCertificateErrors() = 0; - // The frame loaded a resource with an otherwise-valid legacy Symantec - // certificate that is slated for distrust. Prints a console message (possibly - // overridden by the embedder) to warn about the certificate. - virtual void ReportLegacySymantecCert(const KURL&) {} + // The frame loaded a resource with a legacy Symantec certificate that is + // slated for distrust (indicated by |did_fail| being false) or has already + // been distrusted (indicated by |did_fail| being true). Prints a console + // message (possibly overridden by the embedder) to warn about the + // certificate. + virtual void ReportLegacySymantecCert(const KURL&, bool did_fail) {} // Will be called when |PerformanceTiming| events are updated virtual void DidChangePerformanceTiming() {}
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index e460ded..cae9c384 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1783,11 +1783,20 @@ // layer->SubtreeIsInvisible() here. layout_object->SetMayNeedPaintInvalidationSubtree(); if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && - RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { + RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && + !layer->NeedsRepaint()) { // Paint properties of the layer relative to its containing graphics // layer may change if the paint properties escape the graphics layer's - // property state. - layer->SetNeedsRepaint(); + // property state. Need to check raster invalidation for relative paint + // property changes. + if (auto* paint_invalidation_layer = + layer->EnclosingLayerForPaintInvalidation()) { + auto* mapping = paint_invalidation_layer->GetCompositedLayerMapping(); + if (!mapping) + mapping = paint_invalidation_layer->GroupedMapping(); + if (mapping) + mapping->SetNeedsCheckRasterInvalidation(); + } } TRACE_EVENT_INSTANT1(
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp index 850c1d0b..9c8c75e 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
@@ -185,7 +185,7 @@ mime_type_(mime_type), start_time_(start_time), static_bitmap_image_loaded_(false), - callback_(V8PersistentCallbackFunction<V8BlobCallback>::Create(callback)), + callback_(ToV8PersistentCallbackFunction(callback)), script_promise_resolver_(resolver) { DCHECK(image); sk_sp<SkImage> skia_image = image_->PaintImageForCurrentFrame().GetSkImage(); @@ -401,7 +401,8 @@ if (function_type_ == kHTMLCanvasToBlobCallback) { context_->GetTaskRunner(TaskType::kCanvasBlobSerialization) ->PostTask(FROM_HERE, - WTF::Bind(&V8BlobCallback::InvokeAndReportException, + WTF::Bind(&V8PersistentCallbackFunction< + V8BlobCallback>::InvokeAndReportException, WrapPersistent(callback_.Get()), nullptr, WrapPersistent(result_blob))); } else { @@ -419,7 +420,8 @@ context_->GetTaskRunner(TaskType::kCanvasBlobSerialization) ->PostTask( FROM_HERE, - WTF::Bind(&V8BlobCallback::InvokeAndReportException, + WTF::Bind(&V8PersistentCallbackFunction< + V8BlobCallback>::InvokeAndReportException, WrapPersistent(callback_.Get()), nullptr, nullptr)); } else { script_promise_resolver_->Reject(DOMException::Create(
diff --git a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp index 9fc6558e..3a2834d 100644 --- a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
@@ -862,10 +862,12 @@ // If the canvas element's bitmap has no pixels GetDocument() .GetTaskRunner(TaskType::kCanvasBlobSerialization) - ->PostTask(FROM_HERE, - WTF::Bind(&V8BlobCallback::InvokeAndReportException, - WrapPersistentCallbackFunction(callback), nullptr, - nullptr)); + ->PostTask( + FROM_HERE, + WTF::Bind(&V8PersistentCallbackFunction< + V8BlobCallback>::InvokeAndReportException, + WrapPersistent(ToV8PersistentCallbackFunction(callback)), + nullptr, nullptr)); return; } @@ -894,10 +896,12 @@ } else { GetDocument() .GetTaskRunner(TaskType::kCanvasBlobSerialization) - ->PostTask(FROM_HERE, - WTF::Bind(&V8BlobCallback::InvokeAndReportException, - WrapPersistentCallbackFunction(callback), nullptr, - nullptr)); + ->PostTask( + FROM_HERE, + WTF::Bind(&V8PersistentCallbackFunction< + V8BlobCallback>::InvokeAndReportException, + WrapPersistent(ToV8PersistentCallbackFunction(callback)), + nullptr, nullptr)); return; } }
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp index 19675e16..eb8f7c9 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -81,6 +81,7 @@ #include "platform/mhtml/MHTMLArchive.h" #include "platform/network/ContentSecurityPolicyResponseHeaders.h" #include "platform/network/HTTPParsers.h" +#include "platform/network/NetworkUtils.h" #include "platform/network/http_names.h" #include "platform/network/mime/MIMETypeRegistry.h" #include "platform/plugins/PluginData.h" @@ -995,7 +996,8 @@ // Report legacy Symantec certificates after Page::DidCommitLoad, because the // latter clears the console. if (response_.IsLegacySymantecCert()) { - GetLocalFrameClient().ReportLegacySymantecCert(response_.Url()); + GetLocalFrameClient().ReportLegacySymantecCert(response_.Url(), + false /* did_fail */); } }
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp index 9b43f07..947329f 100644 --- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -65,7 +65,6 @@ #include "public/platform/Platform.h" #include "public/platform/TaskType.h" #include "public/platform/WebCORS.h" -#include "public/platform/WebCORSPreflightResultCache.h" #include "public/platform/WebSecurityOrigin.h" #include "public/platform/WebURLRequest.h" #include "services/network/public/mojom/cors.mojom-blink.h" @@ -576,7 +575,7 @@ probe::shouldForceCORSPreflight(GetExecutionContext(), &should_ignore_preflight_cache); if (should_ignore_preflight_cache || - !WebCORSPreflightResultCache::Shared().CanSkipPreflight( + !CORS::CheckIfRequestCanSkipPreflight( GetSecurityOrigin()->ToString(), cross_origin_request.Url(), cross_origin_request.GetFetchCredentialsMode(), cross_origin_request.HttpMethod(), @@ -937,8 +936,8 @@ } } - WebString access_control_error_description; - if (!WebCORSPreflightResultCache::Shared().EnsureResultAndMayAppendEntry( + String access_control_error_description; + if (!CORS::EnsurePreflightResultAndCacheOnSuccess( response.HttpHeaderFields(), GetSecurityOrigin()->ToString(), actual_request_.Url(), actual_request_.HttpMethod(), actual_request_.HttpHeaderFields(),
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 127aa23..cfc5083f 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -574,7 +574,8 @@ } if (response.IsLegacySymantecCert()) { - GetLocalFrameClient()->ReportLegacySymantecCert(response.Url()); + GetLocalFrameClient()->ReportLegacySymantecCert(response.Url(), + false /* did_fail */); } GetFrame()->Loader().Progress().IncrementProgress(identifier, response); @@ -645,7 +646,8 @@ } } -void FrameFetchContext::DispatchDidFail(unsigned long identifier, +void FrameFetchContext::DispatchDidFail(const KURL& url, + unsigned long identifier, const ResourceError& error, int64_t encoded_data_length, bool is_internal_request) { @@ -658,6 +660,10 @@ WebFeature::kCertificateTransparencyRequiredErrorOnResourceLoad); } + if (NetworkUtils::IsLegacySymantecCertError(error.ErrorCode())) { + GetLocalFrameClient()->ReportLegacySymantecCert(url, true /* did_fail */); + } + GetFrame()->Loader().Progress().CompleteProgress(identifier); probe::didFailLoading(GetFrame()->GetDocument(), identifier, MasterDocumentLoader(), error);
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h index 8032864..fc6bff4 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -114,7 +114,8 @@ int64_t encoded_data_length, int64_t decoded_body_length, bool blocked_cross_site_document) override; - void DispatchDidFail(unsigned long identifier, + void DispatchDidFail(const KURL&, + unsigned long identifier, const ResourceError&, int64_t encoded_data_length, bool is_internal_request) override;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp index a5b615a..f176a033 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -1362,8 +1362,8 @@ TEST_F(FrameFetchContextTest, DispatchDidFailWhenDetached) { dummy_page_holder = nullptr; - fetch_context->DispatchDidFail(8, ResourceError::Failure(NullURL()), 5, - false); + fetch_context->DispatchDidFail(KURL(), 8, ResourceError::Failure(NullURL()), + 5, false); // Should not crash. }
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp index 33f3b767..3a7bcf8 100644 --- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -343,7 +343,8 @@ blocked_cross_site_document); } -void WorkerFetchContext::DispatchDidFail(unsigned long identifier, +void WorkerFetchContext::DispatchDidFail(const KURL& url, + unsigned long identifier, const ResourceError& error, int64_t encoded_data_length, bool is_internal_request) {
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h index dcb4471..cc3bec17 100644 --- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h +++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
@@ -95,7 +95,8 @@ int64_t encoded_data_length, int64_t decoded_body_length, bool blocked_cross_site_document) override; - void DispatchDidFail(unsigned long identifier, + void DispatchDidFail(const KURL&, + unsigned long identifier, const ResourceError&, int64_t encoded_data_length, bool isInternalRequest) override;
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp index 6ac681c..571120d0 100644 --- a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp +++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
@@ -14,12 +14,6 @@ namespace blink { -static void RunWatchCallback(V8MojoWatchCallback* callback, - ScriptWrappable* wrappable, - MojoResult result) { - callback->InvokeAndReportException(wrappable, result); -} - // static MojoWatcher* MojoWatcher::Create(mojo::Handle handle, const MojoHandleSignals& signals_dict, @@ -37,8 +31,11 @@ // is scheduled. if (result != MOJO_RESULT_OK) { watcher->task_runner_->PostTask( - FROM_HERE, WTF::Bind(&RunWatchCallback, WrapPersistent(callback), - WrapPersistent(watcher), result)); + FROM_HERE, + WTF::Bind(&V8PersistentCallbackFunction< + V8MojoWatchCallback>::InvokeAndReportException, + WrapPersistent(ToV8PersistentCallbackFunction(callback)), + WrapPersistent(watcher), result)); } return watcher; } @@ -171,7 +168,7 @@ // been reset. if (watcher_handle_.is_valid()) { watcher_handle_.reset(); - RunWatchCallback(callback_, this, result); + callback_->InvokeAndReportException(this, result); } return; } @@ -180,7 +177,7 @@ if (!watcher_handle_.is_valid()) return; - RunWatchCallback(callback_, this, result); + callback_->InvokeAndReportException(this, result); // The user callback may have canceled watching. if (!watcher_handle_.is_valid())
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollStateCallback.h b/third_party/WebKit/Source/core/page/scrolling/ScrollStateCallback.h index 77a5732..34fb16a 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollStateCallback.h +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollStateCallback.h
@@ -60,8 +60,7 @@ V8ScrollStateCallback* callback, WebNativeScrollBehavior native_scroll_behavior) : ScrollStateCallback(native_scroll_behavior), - callback_(V8PersistentCallbackFunction<V8ScrollStateCallback>::Create( - callback)) {} + callback_(ToV8PersistentCallbackFunction(callback)) {} Member<V8PersistentCallbackFunction<V8ScrollStateCallback>> callback_; };
diff --git a/third_party/WebKit/Source/core/paint/BoxPainter.cpp b/third_party/WebKit/Source/core/paint/BoxPainter.cpp index c624a57..1aaae51 100644 --- a/third_party/WebKit/Source/core/paint/BoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
@@ -144,6 +144,7 @@ BoundsForDrawingRecorder(paint_info, LayoutPoint()))) recorder.SetKnownToBeOpaque(); + bool needs_end_layer = false; if (!painting_overflow_contents) { // FIXME: Should eventually give the theme control over whether the box // shadow should paint, since controls could have custom shadows of their @@ -155,8 +156,10 @@ FloatRoundedRect border = style.GetRoundedBorderFor(paint_rect); paint_info.context.ClipRoundedRect(border); - if (box_decoration_data.bleed_avoidance == kBackgroundBleedClipLayer) + if (box_decoration_data.bleed_avoidance == kBackgroundBleedClipLayer) { paint_info.context.BeginLayer(); + needs_end_layer = true; + } } } @@ -202,7 +205,7 @@ } } - if (box_decoration_data.bleed_avoidance == kBackgroundBleedClipLayer) + if (needs_end_layer) paint_info.context.EndLayer(); }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index 2109141..ab3055e 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -303,14 +303,12 @@ const LayoutObject& object, PaintPropertyTreeBuilderContext& full_context, PaintPropertyTreeBuilderFragmentContext& context, - FragmentData& fragment_data, - bool& property_added_or_removed) + FragmentData& fragment_data) : object_(object), full_context_(full_context), context_(context), fragment_data_(fragment_data), - properties_(fragment_data.PaintProperties()), - property_added_or_removed_(property_added_or_removed) {} + properties_(fragment_data.PaintProperties()) {} ~FragmentPaintPropertyTreeBuilder() { full_context_.force_subtree_update |= property_added_or_removed_; @@ -323,6 +321,9 @@ ALWAYS_INLINE void UpdateForSelf(); ALWAYS_INLINE void UpdateForChildren(); + bool PropertyChanged() const { return property_changed_; } + bool PropertyAddedOrRemoved() const { return property_added_or_removed_; } + private: ALWAYS_INLINE void UpdatePaintOffset(); ALWAYS_INLINE void UpdateForPaintOffsetTranslation(Optional<IntPoint>&); @@ -354,12 +355,16 @@ void OnUpdate(const ObjectPaintProperties::UpdateResult& result) { property_added_or_removed_ |= result.NewNodeCreated(); + property_changed_ |= !result.Unchanged(); } void OnUpdateClip(const ObjectPaintProperties::UpdateResult& result) { OnUpdate(result); full_context_.clip_changed |= !result.Unchanged(); } - void OnClear(bool cleared) { property_added_or_removed_ |= cleared; } + void OnClear(bool cleared) { + property_added_or_removed_ |= cleared; + property_changed_ |= cleared; + } void OnClearClip(bool cleared) { OnClear(cleared); full_context_.clip_changed |= cleared; @@ -373,7 +378,8 @@ PaintPropertyTreeBuilderFragmentContext& context_; FragmentData& fragment_data_; ObjectPaintProperties* properties_; - bool& property_added_or_removed_; + bool property_changed_ = false; + bool property_added_or_removed_ = false; }; static bool NeedsScrollNode(const LayoutObject& object) { @@ -2325,7 +2331,7 @@ DCHECK(context_.painting_layer == object_.PaintingLayer()); } -void ObjectPaintPropertyTreeBuilder::UpdateForSelf() { +bool ObjectPaintPropertyTreeBuilder::UpdateForSelf() { UpdatePaintingLayer(); if (ObjectTypeMightNeedPaintProperties()) @@ -2333,12 +2339,15 @@ else object_.GetMutableForPainting().FirstFragment().ClearNextFragment(); + bool property_changed = false; bool property_added_or_removed = false; auto* fragment_data = &object_.GetMutableForPainting().FirstFragment(); for (auto& fragment_context : context_.fragments) { - FragmentPaintPropertyTreeBuilder(object_, context_, fragment_context, - *fragment_data, property_added_or_removed) - .UpdateForSelf(); + FragmentPaintPropertyTreeBuilder builder(object_, context_, + fragment_context, *fragment_data); + builder.UpdateForSelf(); + property_changed |= builder.PropertyChanged(); + property_added_or_removed |= builder.PropertyAddedOrRemoved(); fragment_data = fragment_data->NextFragment(); } DCHECK(!fragment_data); @@ -2347,18 +2356,23 @@ if (property_added_or_removed && RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) context_.painting_layer->SetNeedsRepaint(); + + return property_changed; } -void ObjectPaintPropertyTreeBuilder::UpdateForChildren() { +bool ObjectPaintPropertyTreeBuilder::UpdateForChildren() { if (!ObjectTypeMightNeedPaintProperties()) - return; + return false; + bool property_changed = false; bool property_added_or_removed = false; auto* fragment_data = &object_.GetMutableForPainting().FirstFragment(); for (auto& fragment_context : context_.fragments) { - FragmentPaintPropertyTreeBuilder(object_, context_, fragment_context, - *fragment_data, property_added_or_removed) - .UpdateForChildren(); + FragmentPaintPropertyTreeBuilder builder(object_, context_, + fragment_context, *fragment_data); + builder.UpdateForChildren(); + property_changed |= builder.PropertyChanged(); + property_added_or_removed |= builder.PropertyAddedOrRemoved(); context_.force_subtree_update |= object_.SubtreeNeedsPaintPropertyUpdate(); fragment_data = fragment_data->NextFragment(); } @@ -2373,6 +2387,8 @@ if (property_added_or_removed && RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) context_.painting_layer->SetNeedsRepaint(); + + return property_changed; } } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h index 264c8b65..d92a9c8f 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -176,11 +176,13 @@ // Update the paint properties that affect this object (e.g., properties like // paint offset translation) and ensure the context is up to date. Also // handles updating the object's paintOffset. - void UpdateForSelf(); + // Returns true if any paint property of the object has changed. + bool UpdateForSelf(); // Update the paint properties that affect children of this object (e.g., // scroll offset transform) and ensure the context is up to date. - void UpdateForChildren(); + // Returns true if any paint property of the object has changed. + bool UpdateForChildren(); private: ALWAYS_INLINE void InitFragmentPaintProperties(
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index 2443012..797c7f2a 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -5159,7 +5159,7 @@ SetBodyInnerHTML(R"HTML( <div id="opacity" style="isolation: isolate; width: 100px: height: 100px"> <div id="target" - style="will-change: transform; width: 100px: height: 100gpx"> + style="will-change: transform; width: 100px: height: 100px"> </div> </div> )HTML");
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp index 83eef3b..e2b387b 100644 --- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp +++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -12,6 +12,7 @@ #include "core/layout/LayoutView.h" #include "core/paint/PaintLayer.h" #include "core/paint/PaintPropertyTreePrinter.h" +#include "core/paint/compositing/CompositedLayerMapping.h" #include "core/paint/compositing/CompositingLayerPropertyUpdater.h" #include "core/paint/ng/ng_paint_fragment.h" #include "platform/graphics/paint/GeometryMapper.h" @@ -197,9 +198,10 @@ UpdateAuxiliaryObjectProperties(object, context); Optional<ObjectPaintPropertyTreeBuilder> property_tree_builder; + bool property_changed = false; if (context.tree_builder_context) { property_tree_builder.emplace(object, *context.tree_builder_context); - property_tree_builder->UpdateForSelf(); + property_changed = property_tree_builder->UpdateForSelf(); if (context.tree_builder_context->clip_changed) { context.paint_invalidator_context.subtree_flags |= @@ -213,8 +215,23 @@ context.paint_invalidator_context); if (context.tree_builder_context) { - property_tree_builder->UpdateForChildren(); + property_changed |= property_tree_builder->UpdateForChildren(); InvalidatePaintLayerOptimizationsIfNeeded(object, context); + + if (property_changed && + RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && + !RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + const auto* paint_invalidation_layer = + context.paint_invalidator_context.paint_invalidation_container + ->Layer(); + if (!paint_invalidation_layer->NeedsRepaint()) { + auto* mapping = paint_invalidation_layer->GetCompositedLayerMapping(); + if (!mapping) + mapping = paint_invalidation_layer->GroupedMapping(); + if (mapping) + mapping->SetNeedsCheckRasterInvalidation(); + } + } } CompositingLayerPropertyUpdater::Update(object);
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp index 63039974..253815c 100644 --- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
@@ -3174,6 +3174,15 @@ ApplyToGraphicsLayers(this, functor, kApplyToScrollingContentLayers); } +void CompositedLayerMapping::SetNeedsCheckRasterInvalidation() { + ApplyToGraphicsLayers(this, + [](GraphicsLayer* graphics_layer) { + if (graphics_layer->DrawsContent()) + graphics_layer->SetNeedsCheckRasterInvalidation(); + }, + kApplyToAllGraphicsLayers); +} + const GraphicsLayerPaintInfo* CompositedLayerMapping::ContainingSquashedLayer( const LayoutObject* layout_object, const Vector<GraphicsLayerPaintInfo>& layers,
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.h b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.h index b16b63f..18f8e9bde 100644 --- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.h +++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.h
@@ -191,6 +191,10 @@ PaintInvalidationReason, const DisplayItemClient&); + // Let all DrawsContent GraphicsLayers check raster invalidations after + // a no-change paint. + void SetNeedsCheckRasterInvalidation(); + // Notification from the layoutObject that its content changed. void ContentChanged(ContentChangeType);
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/whatsnew.png b/third_party/WebKit/Source/devtools/front_end/Images/whatsnew.png index 33f10a1..9e34d4e 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/whatsnew.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/whatsnew.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css b/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css index 0f2dcdd..a6e59ca 100644 --- a/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css +++ b/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css
@@ -10,6 +10,7 @@ .widget.ax-subpane { overflow-x: hidden; + -webkit-user-select: text; } div.ax-text-alternatives {
diff --git a/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js b/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js index 9e04bc3..9ede40f 100644 --- a/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js +++ b/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js
@@ -12,6 +12,34 @@ /** @type {!Array<!Help.ReleaseNote>} */ Help.releaseNoteText = [ { + version: 9, + header: 'Highlights from the Chrome 66 update', + highlights: [ + { + title: 'Pretty-printing in the Preview and Response tabs', + subtitle: 'The Preview tab now pretty-prints by default, and you can force ' + + 'pretty-printing in the Response tab via the new Format button.', + link: 'https://developers.google.com/web/updates/2018/02/devtools#pretty-printing', + }, + { + title: 'Previewing HTML content in the Preview tab', + subtitle: 'The Preview tab now always does a basic rendering of HTML content.', + link: 'https://developers.google.com/web/updates/2018/02/devtools#previews', + }, + { + title: 'Local Overrides with styles defined in HTML', + subtitle: 'Local Overrides now works with styles defined in HTML, with one exception.', + link: 'https://developers.google.com/web/updates/2018/02/devtools#overrides', + }, + { + title: 'Blackboxing in the Initiator column', + subtitle: 'Hide framework scripts in order to see the app code that caused a request.', + link: 'https://developers.google.com/web/updates/2018/02/devtools#blackboxing', + }, + ], + link: 'https://developers.google.com/web/updates/2018/02/devtools', + }, + { version: 8, header: 'Highlights from the Chrome 65 update', highlights: [
diff --git a/third_party/WebKit/Source/modules/ModulesExport.h b/third_party/WebKit/Source/modules/ModulesExport.h index 9e2d5f9658..dfec8d1b 100644 --- a/third_party/WebKit/Source/modules/ModulesExport.h +++ b/third_party/WebKit/Source/modules/ModulesExport.h
@@ -2,28 +2,71 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// This header defines macros to export component's symbols. +// See "platform/PlatformExport.h" for details. + #ifndef ModulesExport_h #define ModulesExport_h -#if defined(COMPONENT_BUILD) -#if defined(WIN32) +#include "build/build_config.h" -#if defined(BLINK_MODULES_IMPLEMENTATION) && BLINK_MODULES_IMPLEMENTATION +// +// BLINK_MODULES_IMPLEMENTATION +// +#if !defined(BLINK_MODULES_IMPLEMENTATION) +#define BLINK_MODULES_IMPLEMENTATION 0 +#endif + +// +// MODULES_EXPORT +// +#if !defined(COMPONENT_BUILD) +#define MODULES_EXPORT // No need of export +#else + +#if defined(COMPILER_MSVC) +#if BLINK_MODULES_IMPLEMENTATION #define MODULES_EXPORT __declspec(dllexport) #else #define MODULES_EXPORT __declspec(dllimport) -#endif // defined(BLINK_MODULES_IMPLEMENTATION) && BLINK_MODULES_IMPLEMENTATION +#endif +#endif // defined(COMPILER_MSVC) -#else // defined(WIN32) -#if defined(BLINK_MODULES_IMPLEMENTATION) && BLINK_MODULES_IMPLEMENTATION +#if defined(COMPILER_GCC) +#if BLINK_MODULES_IMPLEMENTATION #define MODULES_EXPORT __attribute__((visibility("default"))) #else #define MODULES_EXPORT #endif +#endif // defined(COMPILER_GCC) + +#endif // !defined(COMPONENT_BUILD) + +// +// MODULES_TEMPLATE_CLASS_EXPORT +// MODULES_EXTERN_TEMPLATE_EXPORT +// MODULES_TEMPLATE_EXPORT +// +#if BLINK_MODULES_IMPLEMENTATION + +#if defined(COMPILER_MSVC) +#define MODULES_TEMPLATE_CLASS_EXPORT +#define MODULES_EXTERN_TEMPLATE_EXPORT MODULES_EXPORT +#define MODULES_TEMPLATE_EXPORT MODULES_EXPORT #endif -#else // defined(COMPONENT_BUILD) -#define MODULES_EXPORT +#if defined(COMPILER_GCC) +#define MODULES_TEMPLATE_CLASS_EXPORT MODULES_EXPORT +#define MODULES_EXTERN_TEMPLATE_EXPORT MODULES_EXPORT +#define MODULES_TEMPLATE_EXPORT #endif +#else // BLINK_MODULES_IMPLEMENTATION + +#define MODULES_TEMPLATE_CLASS_EXPORT +#define MODULES_EXTERN_TEMPLATE_EXPORT MODULES_EXPORT +#define MODULES_TEMPLATE_EXPORT + +#endif // BLINK_MODULES_IMPLEMENTATION + #endif // ModulesExport_h
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchIconLoaderTest.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchIconLoaderTest.cpp index be6c663..af78df8 100644 --- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchIconLoaderTest.cpp +++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchIconLoaderTest.cpp
@@ -17,11 +17,15 @@ namespace blink { namespace { -enum class LoadState { kNotLoaded, kLoadFailed, kLoadSuccessful }; +enum class BackgroundFetchLoadState { + kNotLoaded, + kLoadFailed, + kLoadSuccessful +}; -constexpr char kImageLoaderBaseUrl[] = "http://test.com/"; -constexpr char kImageLoaderBaseDir[] = "notifications/"; -constexpr char kImageLoaderIcon500x500[] = "500x500.png"; +constexpr char kBackgroundFetchImageLoaderBaseUrl[] = "http://test.com/"; +constexpr char kBackgroundFetchImageLoaderBaseDir[] = "notifications/"; +constexpr char kBackgroundFetchImageLoaderIcon500x500[] = "500x500.png"; class BackgroundFetchIconLoaderTest : public PageTestBase { public: @@ -37,7 +41,8 @@ // Registers a mocked URL. WebURL RegisterMockedURL(const String& file_name) { WebURL registered_url = URLTestHelpers::RegisterMockedURLLoadFromBase( - kImageLoaderBaseUrl, testing::CoreTestDataPath(kImageLoaderBaseDir), + kBackgroundFetchImageLoaderBaseUrl, + testing::CoreTestDataPath(kBackgroundFetchImageLoaderBaseDir), file_name, "image/png"); return registered_url; } @@ -47,9 +52,9 @@ void IconLoaded(const SkBitmap& bitmap) { LOG(ERROR) << "did icon get loaded?"; if (!bitmap.empty()) - loaded_ = LoadState::kLoadSuccessful; + loaded_ = BackgroundFetchLoadState::kLoadSuccessful; else - loaded_ = LoadState::kLoadFailed; + loaded_ = BackgroundFetchLoadState::kLoadFailed; } void LoadIcon(const KURL& url) { @@ -62,17 +67,17 @@ protected: ScopedTestingPlatformSupport<TestingPlatformSupport> platform_; - LoadState loaded_ = LoadState::kNotLoaded; + BackgroundFetchLoadState loaded_ = BackgroundFetchLoadState::kNotLoaded; private: Persistent<BackgroundFetchIconLoader> loader_; }; TEST_F(BackgroundFetchIconLoaderTest, SuccessTest) { - KURL url = RegisterMockedURL(kImageLoaderIcon500x500); + KURL url = RegisterMockedURL(kBackgroundFetchImageLoaderIcon500x500); LoadIcon(url); platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); - EXPECT_EQ(LoadState::kLoadSuccessful, loaded_); + EXPECT_EQ(BackgroundFetchLoadState::kLoadSuccessful, loaded_); } } // namespace
diff --git a/third_party/WebKit/Source/modules/clipboard/Clipboard.idl b/third_party/WebKit/Source/modules/clipboard/Clipboard.idl index a6023cc..ecbf5d1 100644 --- a/third_party/WebKit/Source/modules/clipboard/Clipboard.idl +++ b/third_party/WebKit/Source/modules/clipboard/Clipboard.idl
@@ -9,7 +9,8 @@ Exposed=Window ] interface Clipboard : EventTarget { [MeasureAs=AsyncClipboardAPIRead, - CallWith=ScriptState + CallWith=ScriptState, + RuntimeEnabled=AsyncClipboard ] Promise<DataTransfer> read(); [MeasureAs=AsyncClipboardAPIReadText, @@ -17,7 +18,8 @@ ] Promise<DOMString> readText(); [MeasureAs=AsyncClipboardAPIWrite, - CallWith=ScriptState + CallWith=ScriptState, + RuntimeEnabled=AsyncClipboard ] Promise<void> write(DataTransfer data); [MeasureAs=AsyncClipboardAPIWriteText,
diff --git a/third_party/WebKit/Source/modules/clipboard/NavigatorClipboard.idl b/third_party/WebKit/Source/modules/clipboard/NavigatorClipboard.idl index aaa5ee9..f2e2576 100644 --- a/third_party/WebKit/Source/modules/clipboard/NavigatorClipboard.idl +++ b/third_party/WebKit/Source/modules/clipboard/NavigatorClipboard.idl
@@ -5,8 +5,7 @@ // https://w3c.github.io/clipboard-apis/#navigator-interface [ - ImplementedAs=NavigatorClipboard, - RuntimeEnabled=AsyncClipboard + ImplementedAs=NavigatorClipboard ] partial interface Navigator { [CallWith=ScriptState, SecureContext, SameObject] readonly attribute Clipboard clipboard;
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp index e746de7..0972f0c 100644 --- a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp +++ b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
@@ -355,12 +355,8 @@ private: V8Callbacks(V8NavigatorUserMediaSuccessCallback* success_callback, V8NavigatorUserMediaErrorCallback* error_callback) - : success_callback_( - V8PersistentCallbackFunction< - V8NavigatorUserMediaSuccessCallback>::Create(success_callback)), - error_callback_( - V8PersistentCallbackFunction< - V8NavigatorUserMediaErrorCallback>::Create(error_callback)) {} + : success_callback_(ToV8PersistentCallbackFunction(success_callback)), + error_callback_(ToV8PersistentCallbackFunction(error_callback)) {} // As Blink does not hold a UserMediaRequest and lets content/ hold it, // we cannot use wrapper-tracing to keep the underlying callback functions.
diff --git a/third_party/WebKit/Source/modules/nfc/NFC.cpp b/third_party/WebKit/Source/modules/nfc/NFC.cpp index 105d5bd..97d702d 100644 --- a/third_party/WebKit/Source/modules/nfc/NFC.cpp +++ b/third_party/WebKit/Source/modules/nfc/NFC.cpp
@@ -764,7 +764,8 @@ requests_.insert(resolver); auto watch_callback = WTF::Bind(&NFC::OnWatchRegistered, WrapPersistent(this), - WrapPersistent(callback), WrapPersistent(resolver)); + WrapPersistent(ToV8PersistentCallbackFunction(callback)), + WrapPersistent(resolver)); nfc_->Watch(device::mojom::blink::NFCWatchOptions::From(options), std::move(watch_callback)); return resolver->Promise(); @@ -895,10 +896,11 @@ return ScriptPromise(); } -void NFC::OnWatchRegistered(V8MessageCallback* callback, - ScriptPromiseResolver* resolver, - uint32_t id, - device::mojom::blink::NFCErrorPtr error) { +void NFC::OnWatchRegistered( + V8PersistentCallbackFunction<V8MessageCallback>* callback, + ScriptPromiseResolver* resolver, + uint32_t id, + device::mojom::blink::NFCErrorPtr error) { requests_.erase(resolver); // Invalid id was returned. @@ -912,7 +914,7 @@ } if (error.is_null()) { - callbacks_.insert(id, callback); + callbacks_.insert(id, callback->ToNonV8Persistent()); resolver->Resolve(id); } else { resolver->Reject(NFCError::Take(resolver, error->error_type));
diff --git a/third_party/WebKit/Source/modules/nfc/NFC.h b/third_party/WebKit/Source/modules/nfc/NFC.h index 5caed5bc..12300ea 100644 --- a/third_party/WebKit/Source/modules/nfc/NFC.h +++ b/third_party/WebKit/Source/modules/nfc/NFC.h
@@ -75,7 +75,7 @@ void OnRequestCompleted(ScriptPromiseResolver*, device::mojom::blink::NFCErrorPtr); void OnConnectionError(); - void OnWatchRegistered(V8MessageCallback*, + void OnWatchRegistered(V8PersistentCallbackFunction<V8MessageCallback>*, ScriptPromiseResolver*, uint32_t id, device::mojom::blink::NFCErrorPtr);
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp b/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp index 1335d77..9ea65b2 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp
@@ -21,11 +21,11 @@ namespace blink { namespace { -enum class LoadState { kNotLoaded, kLoadFailed, kLoadSuccessful }; +enum class NotificationLoadState { kNotLoaded, kLoadFailed, kLoadSuccessful }; -constexpr char kImageLoaderBaseUrl[] = "http://test.com/"; -constexpr char kImageLoaderBaseDir[] = "notifications/"; -constexpr char kImageLoaderIcon500x500[] = "500x500.png"; +constexpr char kNotificationImageLoaderBaseUrl[] = "http://test.com/"; +constexpr char kNotificationImageLoaderBaseDir[] = "notifications/"; +constexpr char kNotificationImageLoaderIcon500x500[] = "500x500.png"; // This mirrors the definition in NotificationImageLoader.cpp. constexpr unsigned long kImageFetchTimeoutInMs = 90000; @@ -54,8 +54,9 @@ // directory. WebURL RegisterMockedURL(const String& file_name) { WebURL registered_url = URLTestHelpers::RegisterMockedURLLoadFromBase( - kImageLoaderBaseUrl, testing::CoreTestDataPath(kImageLoaderBaseDir), - file_name, "image/png"); + kNotificationImageLoaderBaseUrl, + testing::CoreTestDataPath(kNotificationImageLoaderBaseDir), file_name, + "image/png"); return registered_url; } @@ -63,9 +64,9 @@ // load as either success or failed based on whether the bitmap is empty. void ImageLoaded(const SkBitmap& bitmap) { if (!bitmap.empty()) - loaded_ = LoadState::kLoadSuccessful; + loaded_ = NotificationLoadState::kLoadSuccessful; else - loaded_ = LoadState::kLoadFailed; + loaded_ = NotificationLoadState::kLoadFailed; } void LoadImage(const KURL& url) { @@ -75,7 +76,7 @@ } ExecutionContext* Context() const { return &GetDocument(); } - LoadState Loaded() const { return loaded_; } + NotificationLoadState Loaded() const { return loaded_; } protected: HistogramTester histogram_tester_; @@ -83,17 +84,17 @@ private: Persistent<NotificationImageLoader> loader_; - LoadState loaded_ = LoadState::kNotLoaded; + NotificationLoadState loaded_ = NotificationLoadState::kNotLoaded; }; TEST_F(NotificationImageLoaderTest, SuccessTest) { - KURL url = RegisterMockedURL(kImageLoaderIcon500x500); + KURL url = RegisterMockedURL(kNotificationImageLoaderIcon500x500); LoadImage(url); histogram_tester_.ExpectTotalCount("Notifications.LoadFinishTime.Icon", 0); histogram_tester_.ExpectTotalCount("Notifications.LoadFileSize.Icon", 0); histogram_tester_.ExpectTotalCount("Notifications.LoadFailTime.Icon", 0); platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); - EXPECT_EQ(LoadState::kLoadSuccessful, Loaded()); + EXPECT_EQ(NotificationLoadState::kLoadSuccessful, Loaded()); histogram_tester_.ExpectTotalCount("Notifications.LoadFinishTime.Icon", 1); histogram_tester_.ExpectUniqueSample("Notifications.LoadFileSize.Icon", 7439, 1); @@ -106,13 +107,13 @@ // To test for a timeout, this needs to override the clock in the platform. // Just creating the mock platform will do everything to set it up. - KURL url = RegisterMockedURL(kImageLoaderIcon500x500); + KURL url = RegisterMockedURL(kNotificationImageLoaderIcon500x500); LoadImage(url); // Run the platform for kImageFetchTimeoutInMs-1 seconds. This should not // result in a timeout. platform->RunForPeriodSeconds(kImageFetchTimeoutInMs / 1000 - 1); - EXPECT_EQ(LoadState::kNotLoaded, Loaded()); + EXPECT_EQ(NotificationLoadState::kNotLoaded, Loaded()); histogram_tester_.ExpectTotalCount("Notifications.LoadFinishTime.Icon", 0); histogram_tester_.ExpectTotalCount("Notifications.LoadFileSize.Icon", 0); histogram_tester_.ExpectTotalCount("Notifications.LoadFailTime.Icon", 0); @@ -121,7 +122,7 @@ platform->RunForPeriodSeconds(2); // If the loader times out, it calls the callback and returns an empty bitmap. - EXPECT_EQ(LoadState::kLoadFailed, Loaded()); + EXPECT_EQ(NotificationLoadState::kLoadFailed, Loaded()); histogram_tester_.ExpectTotalCount("Notifications.LoadFinishTime.Icon", 0); histogram_tester_.ExpectTotalCount("Notifications.LoadFileSize.Icon", 0); // Should log a non-zero failure time.
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp b/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp index f1884cb..c931098 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp
@@ -5,7 +5,6 @@ #include "modules/notifications/NotificationManager.h" #include "bindings/core/v8/ScriptPromiseResolver.h" -#include "bindings/modules/v8/v8_notification_permission_callback.h" #include "core/frame/Frame.h" #include "core/frame/LocalFrame.h" #include "modules/notifications/Notification.h" @@ -84,16 +83,18 @@ permission_service_->RequestPermission( CreatePermissionDescriptor(mojom::blink::PermissionName::NOTIFICATIONS), Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr), - WTF::Bind(&NotificationManager::OnPermissionRequestComplete, - WrapPersistent(this), WrapPersistent(resolver), - WrapPersistentCallbackFunction(deprecated_callback))); + WTF::Bind( + &NotificationManager::OnPermissionRequestComplete, + WrapPersistent(this), WrapPersistent(resolver), + WrapPersistent(ToV8PersistentCallbackFunction(deprecated_callback)))); return promise; } void NotificationManager::OnPermissionRequestComplete( ScriptPromiseResolver* resolver, - V8NotificationPermissionCallback* deprecated_callback, + V8PersistentCallbackFunction<V8NotificationPermissionCallback>* + deprecated_callback, mojom::blink::PermissionStatus status) { String status_string = Notification::PermissionString(status); if (deprecated_callback)
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationManager.h b/third_party/WebKit/Source/modules/notifications/NotificationManager.h index ff9af29..063209a2 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationManager.h +++ b/third_party/WebKit/Source/modules/notifications/NotificationManager.h
@@ -5,6 +5,7 @@ #ifndef NotificationManager_h #define NotificationManager_h +#include "bindings/modules/v8/v8_notification_permission_callback.h" #include "core/dom/ExecutionContext.h" #include "platform/wtf/Noncopyable.h" #include "platform/wtf/text/WTFString.h" @@ -17,7 +18,6 @@ class ScriptPromise; class ScriptPromiseResolver; class ScriptState; -class V8NotificationPermissionCallback; struct WebNotificationData; // The notification manager, unique to the execution context, is responsible for @@ -79,9 +79,10 @@ // established the first time this method is called. const mojom::blink::NotificationServicePtr& GetNotificationService(); - void OnPermissionRequestComplete(ScriptPromiseResolver*, - V8NotificationPermissionCallback*, - mojom::blink::PermissionStatus); + void OnPermissionRequestComplete( + ScriptPromiseResolver*, + V8PersistentCallbackFunction<V8NotificationPermissionCallback>*, + mojom::blink::PermissionStatus); void OnNotificationServiceConnectionError(); void OnPermissionServiceConnectionError();
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp index 6fdf257..9f4a07e3 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp +++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
@@ -137,9 +137,10 @@ DOMException* exception) { DCHECK(error_callback); Microtask::EnqueueMicrotask( - WTF::Bind(&V8RTCPeerConnectionErrorCallback::InvokeAndReportException, - WrapPersistentCallbackFunction(error_callback), nullptr, - WrapPersistent(exception))); + WTF::Bind(&V8PersistentCallbackFunction< + V8RTCPeerConnectionErrorCallback>::InvokeAndReportException, + WrapPersistent(ToV8PersistentCallbackFunction(error_callback)), + nullptr, WrapPersistent(exception))); } bool CallErrorCallbackIfSignalingStateClosed(
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp index 7ed2701..340ee16 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp +++ b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp
@@ -54,12 +54,8 @@ V8RTCSessionDescriptionCallback* success_callback, V8RTCPeerConnectionErrorCallback* error_callback) : ContextLifecycleObserver(context), - success_callback_( - V8PersistentCallbackFunction<V8RTCSessionDescriptionCallback>::Create( - success_callback)), - error_callback_( - V8PersistentCallbackFunction< - V8RTCPeerConnectionErrorCallback>::Create(error_callback)), + success_callback_(ToV8PersistentCallbackFunction(success_callback)), + error_callback_(ToV8PersistentCallbackFunction(error_callback)), requester_(requester) { DCHECK(requester_); }
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCStatsRequestImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCStatsRequestImpl.cpp index d30d1d0..bc293fe 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCStatsRequestImpl.cpp +++ b/third_party/WebKit/Source/modules/peerconnection/RTCStatsRequestImpl.cpp
@@ -41,8 +41,7 @@ V8RTCStatsCallback* callback, MediaStreamTrack* selector) : ContextLifecycleObserver(context), - success_callback_( - V8PersistentCallbackFunction<V8RTCStatsCallback>::Create(callback)), + success_callback_(ToV8PersistentCallbackFunction(callback)), component_(selector ? selector->Component() : nullptr), requester_(requester) { DCHECK(requester_);
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestImpl.cpp index 481907ca..a9c15d8f 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestImpl.cpp +++ b/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestImpl.cpp
@@ -51,11 +51,8 @@ V8VoidFunction* success_callback, V8RTCPeerConnectionErrorCallback* error_callback) : ContextLifecycleObserver(context), - success_callback_(V8PersistentCallbackFunction<V8VoidFunction>::Create( - success_callback)), - error_callback_( - V8PersistentCallbackFunction< - V8RTCPeerConnectionErrorCallback>::Create(error_callback)), + success_callback_(ToV8PersistentCallbackFunction(success_callback)), + error_callback_(ToV8PersistentCallbackFunction(error_callback)), requester_(requester) { DCHECK(requester_); }
diff --git a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp index f29512ae..724d2c8 100644 --- a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp +++ b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
@@ -65,8 +65,8 @@ } void DeprecatedQueryStorageUsageAndQuotaCallback( - V8StorageUsageCallback* success_callback, - V8StorageErrorCallback* error_callback, + V8PersistentCallbackFunction<V8StorageUsageCallback>* success_callback, + V8PersistentCallbackFunction<V8StorageErrorCallback>* error_callback, mojom::QuotaStatusCode status_code, int64_t usage_in_bytes, int64_t quota_in_bytes) { @@ -84,11 +84,12 @@ } } -void RequestStorageQuotaCallback(V8StorageQuotaCallback* success_callback, - V8StorageErrorCallback* error_callback, - mojom::QuotaStatusCode status_code, - int64_t usage_in_bytes, - int64_t granted_quota_in_bytes) { +void RequestStorageQuotaCallback( + V8PersistentCallbackFunction<V8StorageQuotaCallback>* success_callback, + V8PersistentCallbackFunction<V8StorageErrorCallback>* error_callback, + mojom::QuotaStatusCode status_code, + int64_t usage_in_bytes, + int64_t granted_quota_in_bytes) { if (status_code != mojom::QuotaStatusCode::kOk) { if (error_callback) { error_callback->InvokeAndReportException( @@ -115,9 +116,11 @@ ->GetTaskRunner(TaskType::kMiscPlatformAPI) ->PostTask( FROM_HERE, - WTF::Bind(&V8StorageErrorCallback::InvokeAndReportException, - WrapPersistentCallbackFunction(error_callback), nullptr, - WrapPersistent(DOMError::Create(exception_code)))); + WTF::Bind( + &V8PersistentCallbackFunction< + V8StorageErrorCallback>::InvokeAndReportException, + WrapPersistent(ToV8PersistentCallbackFunction(error_callback)), + nullptr, WrapPersistent(DOMError::Create(exception_code)))); } DeprecatedStorageQuota::DeprecatedStorageQuota(Type type) : type_(type) {} @@ -146,9 +149,10 @@ return; } - auto callback = WTF::Bind(&DeprecatedQueryStorageUsageAndQuotaCallback, - WrapPersistentCallbackFunction(success_callback), - WrapPersistentCallbackFunction(error_callback)); + auto callback = WTF::Bind( + &DeprecatedQueryStorageUsageAndQuotaCallback, + WrapPersistent(ToV8PersistentCallbackFunction(success_callback)), + WrapPersistent(ToV8PersistentCallbackFunction(error_callback))); GetQuotaHost(execution_context) .QueryStorageUsageAndQuota( WrapRefCounted(security_origin), storage_type, @@ -175,9 +179,10 @@ return; } - auto callback = WTF::Bind(&RequestStorageQuotaCallback, - WrapPersistentCallbackFunction(success_callback), - WrapPersistentCallbackFunction(error_callback)); + auto callback = WTF::Bind( + &RequestStorageQuotaCallback, + WrapPersistent(ToV8PersistentCallbackFunction(success_callback)), + WrapPersistent(ToV8PersistentCallbackFunction(error_callback))); Document* document = ToDocument(execution_context); const SecurityOrigin* security_origin = document->GetSecurityOrigin();
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp index e9c9a1c6..e9bf8844 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
@@ -25,6 +25,7 @@ #include "modules/webaudio/AudioParamDescriptor.h" #include "modules/webaudio/AudioWorkletProcessor.h" #include "modules/webaudio/AudioWorkletProcessorDefinition.h" +#include "modules/webaudio/AudioWorkletProcessorErrorState.h" #include "modules/webaudio/CrossThreadAudioWorkletProcessorInfo.h" #include "platform/audio/AudioBus.h" #include "platform/audio/AudioUtilities.h" @@ -175,7 +176,7 @@ return nullptr; } - // ToImplWithTypeCheck() may return nullptr whenthe type does not match. + // ToImplWithTypeCheck() may return nullptr when the type does not match. AudioWorkletProcessor* processor = V8AudioWorkletProcessor::ToImplWithTypeCheck(isolate, result); @@ -317,7 +318,7 @@ // process() method call method call failed for some reason or an exception // was thrown by the user supplied code. Disable the processor to exclude // it from the subsequent rendering task. - processor->MarkNonRunnable(); + processor->SetErrorState(AudioWorkletProcessorErrorState::kProcessError); return false; }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp index 657ae632..2da78f2 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
@@ -79,8 +79,8 @@ void AudioWorkletHandler::Process(size_t frames_to_process) { DCHECK(Context()->IsAudioThread()); - // Render and update the node state when the processor is ready and runnable. - if (processor_ && processor_->IsRunnable()) { + // Render and update the node state when the processor is ready with no error. + if (processor_ && !processor_->hasErrorOccured()) { Vector<AudioBus*> inputBuses; Vector<AudioBus*> outputBuses; for (unsigned i = 0; i < NumberOfInputs(); ++i) @@ -104,12 +104,12 @@ // Run the render code and check the state of processor. Finish the // processor if needed. if (!processor_->Process(&inputBuses, &outputBuses, ¶m_value_map_) || - !processor_->IsRunnable()) { + processor_->hasErrorOccured()) { FinishProcessorOnRenderThread(); } } else { // The initialization of handler or the associated processor might not be - // ready yet or it is in 'non-runnable' state. If so, zero out the connected + // ready yet or it is in the error state. If so, zero out the connected // output. for (unsigned i = 0; i < NumberOfOutputs(); ++i) { Output(i).Bus()->Zero(); @@ -149,30 +149,31 @@ DCHECK(!IsMainThread()); // |processor| can be nullptr when the invocation of user-supplied constructor - // fails. That failure sets the processor to "error" state. - processor_ = processor; - AudioWorkletProcessorState new_state; - new_state = processor_ ? AudioWorkletProcessorState::kRunning - : AudioWorkletProcessorState::kError; - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBind(&AudioWorkletHandler::NotifyProcessorStateChange, - WrapRefCounted(this), new_state)); + // fails. That failure fires at the node's 'onprocessorerror' event handler. + if (processor) { + processor_ = processor; + } else { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBind(&AudioWorkletHandler::NotifyProcessorError, + WrapRefCounted(this), + AudioWorkletProcessorErrorState::kConstructionError)); + } } void AudioWorkletHandler::FinishProcessorOnRenderThread() { DCHECK(Context()->IsAudioThread()); - // The non-runnable processor means that the processor stopped due to an - // exception thrown by the user-supplied code. - AudioWorkletProcessorState new_state; - new_state = processor_->IsRunnable() - ? AudioWorkletProcessorState::kStopped - : AudioWorkletProcessorState::kError; - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBind(&AudioWorkletHandler::NotifyProcessorStateChange, - WrapRefCounted(this), new_state)); + // If the user-supplied code is not runnable (i.e. threw an exception) + // anymore after the process() call above. Invoke error on the main thread. + AudioWorkletProcessorErrorState error_state = processor_->GetErrorState(); + if (error_state == AudioWorkletProcessorErrorState::kProcessError) { + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBind(&AudioWorkletHandler::NotifyProcessorError, + WrapRefCounted(this), + error_state)); + } // TODO(hongchan): After this point, The handler has no more pending activity // and ready for GC. @@ -181,12 +182,13 @@ tail_time_ = 0; } -void AudioWorkletHandler::NotifyProcessorStateChange( - AudioWorkletProcessorState state) { +void AudioWorkletHandler::NotifyProcessorError( + AudioWorkletProcessorErrorState error_state) { DCHECK(IsMainThread()); if (!Context() || !Context()->GetExecutionContext() || !GetNode()) return; - static_cast<AudioWorkletNode*>(GetNode())->SetProcessorState(state); + + static_cast<AudioWorkletNode*>(GetNode())->FireProcessorError(); } // ---------------------------------------------------------------- @@ -198,8 +200,7 @@ const Vector<CrossThreadAudioParamInfo> param_info_list, MessagePort* node_port) : AudioNode(context), - node_port_(node_port), - processor_state_(AudioWorkletProcessorState::kPending) { + node_port_(node_port) { HeapHashMap<String, Member<AudioParam>> audio_param_map; HashMap<String, scoped_refptr<AudioParamHandler>> param_handler_map; for (const auto& param_info : param_info_list) { @@ -348,51 +349,18 @@ return !context()->IsContextClosed(); } -void AudioWorkletNode::SetProcessorState(AudioWorkletProcessorState new_state) { - DCHECK(IsMainThread()); - switch (processor_state_) { - case AudioWorkletProcessorState::kPending: - DCHECK(new_state == AudioWorkletProcessorState::kRunning || - new_state == AudioWorkletProcessorState::kError); - break; - case AudioWorkletProcessorState::kRunning: - DCHECK(new_state == AudioWorkletProcessorState::kStopped || - new_state == AudioWorkletProcessorState::kError); - break; - case AudioWorkletProcessorState::kStopped: - case AudioWorkletProcessorState::kError: - NOTREACHED() - << "The state never changes once it reaches kStopped or kError."; - return; - } - - processor_state_ = new_state; - DispatchEvent(Event::Create(EventTypeNames::processorstatechange)); -} - AudioParamMap* AudioWorkletNode::parameters() const { return parameter_map_; } -String AudioWorkletNode::processorState() const { - switch (processor_state_) { - case AudioWorkletProcessorState::kPending: - return "pending"; - case AudioWorkletProcessorState::kRunning: - return "running"; - case AudioWorkletProcessorState::kStopped: - return "stopped"; - case AudioWorkletProcessorState::kError: - return "error"; - } - NOTREACHED(); - return g_empty_string; -} - MessagePort* AudioWorkletNode::port() const { return node_port_; } +void AudioWorkletNode::FireProcessorError() { + DispatchEvent(Event::Create(EventTypeNames::processorerror)); +} + AudioWorkletHandler& AudioWorkletNode::GetWorkletHandler() const { return static_cast<AudioWorkletHandler&>(Handler()); }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h index 7869e86..da611e7 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.h
@@ -9,6 +9,7 @@ #include "modules/webaudio/AudioNode.h" #include "modules/webaudio/AudioParamMap.h" #include "modules/webaudio/AudioWorkletNodeOptions.h" +#include "modules/webaudio/AudioWorkletProcessorErrorState.h" #include "platform/wtf/Threading.h" namespace blink { @@ -21,13 +22,6 @@ class MessagePort; class ScriptState; -enum class AudioWorkletProcessorState { - kPending, - kRunning, - kStopped, - kError, -}; - // AudioWorkletNode is a user-facing interface of custom audio processor in // Web Audio API. The integration of WebAudio renderer is done via // AudioWorkletHandler and the actual audio processing runs on @@ -66,7 +60,7 @@ // the user-supplied |process()| method returns false. void FinishProcessorOnRenderThread(); - void NotifyProcessorStateChange(AudioWorkletProcessorState); + void NotifyProcessorError(AudioWorkletProcessorErrorState); private: AudioWorkletHandler( @@ -107,13 +101,12 @@ // ActiveScriptWrappable bool HasPendingActivity() const final; - void SetProcessorState(AudioWorkletProcessorState); - // IDL AudioParamMap* parameters() const; MessagePort* port() const; - String processorState() const; - DEFINE_ATTRIBUTE_EVENT_LISTENER(processorstatechange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(processorerror); + + void FireProcessorError(); virtual void Trace(blink::Visitor*); @@ -126,7 +119,6 @@ Member<AudioParamMap> parameter_map_; Member<MessagePort> node_port_; - AudioWorkletProcessorState processor_state_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl index 7283c0d..a4632e9 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.idl
@@ -4,13 +4,6 @@ // https://webaudio.github.io/web-audio-api/#AudioWorkletNode -enum AudioWorkletProcessorState { - "pending", - "running", - "stopped", - "error" -}; - [ ActiveScriptWrappable, Constructor(BaseAudioContext context, DOMString name, optional AudioWorkletNodeOptions options), @@ -22,6 +15,5 @@ ] interface AudioWorkletNode : AudioNode { readonly attribute AudioParamMap parameters; readonly attribute MessagePort port; - readonly attribute AudioWorkletProcessorState processorState; - attribute EventHandler onprocessorstatechange; + attribute EventHandler onprocessorerror; };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp index f513a6d..061c88a 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.cpp
@@ -37,11 +37,24 @@ Vector<AudioBus*>* output_buses, HashMap<String, std::unique_ptr<AudioFloatArray>>* param_value_map) { DCHECK(global_scope_->IsContextThread()); - DCHECK(IsRunnable()); + DCHECK(!hasErrorOccured()); return global_scope_->Process(this, input_buses, output_buses, param_value_map); } +void AudioWorkletProcessor::SetErrorState( + AudioWorkletProcessorErrorState error_state) { + error_state_ = error_state; +} + +AudioWorkletProcessorErrorState AudioWorkletProcessor::GetErrorState() const { + return error_state_; +} + +bool AudioWorkletProcessor::hasErrorOccured() const { + return error_state_ != AudioWorkletProcessorErrorState::kNoError; +} + MessagePort* AudioWorkletProcessor::port() const { return processor_port_.Get(); }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h index 35df1e5..66e702b6 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessor.h
@@ -6,6 +6,7 @@ #define AudioWorkletProcessor_h #include "modules/ModulesExport.h" +#include "modules/webaudio/AudioWorkletProcessorErrorState.h" #include "platform/audio/AudioArray.h" #include "platform/bindings/ScriptWrappable.h" #include "platform/bindings/TraceWrapperV8Reference.h" @@ -47,11 +48,9 @@ const String& Name() const { return name_; } - // Mark this processor as "not runnable" so it does not execute the - // user-supplied code even after the associated node is connected to the - // graph. - void MarkNonRunnable() { is_runnable_ = false; } - bool IsRunnable() { return is_runnable_; } + void SetErrorState(AudioWorkletProcessorErrorState); + AudioWorkletProcessorErrorState GetErrorState() const; + bool hasErrorOccured() const; // IDL MessagePort* port() const; @@ -68,9 +67,8 @@ const String name_; - // Becomes |false| when Process() method throws an exception from the the - // user-supplied code. It is an irreversible transition. - bool is_runnable_ = true; + AudioWorkletProcessorErrorState error_state_ = + AudioWorkletProcessorErrorState::kNoError; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorErrorState.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorErrorState.h new file mode 100644 index 0000000..9968f86 --- /dev/null +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorErrorState.h
@@ -0,0 +1,25 @@ +// 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 AudioWorkletProcessorErrorState_h +#define AudioWorkletProcessorErrorState_h + +namespace blink { + +// A list of state regarding the error in AudioWorkletProcessor object. +enum class AudioWorkletProcessorErrorState : unsigned { + // The constructor or the process method in the processor has not thrown any + // exception. + kNoError = 0, + + // An exception thrown from the construction failure. + kConstructionError = 1, + + // An exception thrown from the process method. + kProcessError = 2, +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/modules/webaudio/BUILD.gn b/third_party/WebKit/Source/modules/webaudio/BUILD.gn index ee8d3e8..8c70ef0d 100644 --- a/third_party/WebKit/Source/modules/webaudio/BUILD.gn +++ b/third_party/WebKit/Source/modules/webaudio/BUILD.gn
@@ -56,6 +56,7 @@ "AudioWorkletProcessor.h", "AudioWorkletProcessorDefinition.cpp", "AudioWorkletProcessorDefinition.h", + "AudioWorkletProcessorErrorState.h", "AudioWorkletThread.cpp", "AudioWorkletThread.h", "BaseAudioContext.cpp",
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp index d3db078..68890b9 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -314,12 +314,8 @@ decode_audio_resolvers_.insert(resolver); audio_decoder_.DecodeAsync( - audio, rate, - V8PersistentCallbackFunction<V8DecodeSuccessCallback>::Create( - success_callback), - V8PersistentCallbackFunction<V8DecodeErrorCallback>::Create( - error_callback), - resolver, this); + audio, rate, ToV8PersistentCallbackFunction(success_callback), + ToV8PersistentCallbackFunction(error_callback), resolver, this); } else { // If audioData is already detached (neutered) we need to reject the // promise with an error.
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp index 9c123ed4..245aff7 100644 --- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -27,7 +27,6 @@ #include <memory> -#include "bindings/modules/v8/v8_database_callback.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/inspector/ConsoleMessage.h" @@ -300,21 +299,24 @@ if (success && IsNew()) { STORAGE_DVLOG(1) << "Scheduling DatabaseCreationCallbackTask for database " << this; + auto* v8persistent_callback = + ToV8PersistentCallbackFunction(creation_callback); probe::AsyncTaskScheduled(GetExecutionContext(), "openDatabase", - creation_callback); + v8persistent_callback); GetExecutionContext() ->GetTaskRunner(TaskType::kDatabaseAccess) ->PostTask( FROM_HERE, WTF::Bind(&Database::RunCreationCallback, WrapPersistent(this), - WrapPersistentCallbackFunction(creation_callback))); + WrapPersistent(v8persistent_callback))); } } return success; } -void Database::RunCreationCallback(V8DatabaseCallback* creation_callback) { +void Database::RunCreationCallback( + V8PersistentCallbackFunction<V8DatabaseCallback>* creation_callback) { probe::AsyncTask async_task(GetExecutionContext(), creation_callback); creation_callback->InvokeAndReportException(nullptr, this); }
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.h b/third_party/WebKit/Source/modules/webdatabase/Database.h index ad6cfcc..13dc743 100644 --- a/third_party/WebKit/Source/modules/webdatabase/Database.h +++ b/third_party/WebKit/Source/modules/webdatabase/Database.h
@@ -27,6 +27,7 @@ #define Database_h #include "base/single_thread_task_runner.h" +#include "bindings/modules/v8/v8_database_callback.h" #include "modules/webdatabase/DatabaseBasicTypes.h" #include "modules/webdatabase/DatabaseError.h" #include "modules/webdatabase/SQLTransaction.h" @@ -46,7 +47,6 @@ class ExecutionContext; class SQLTransactionClient; class SQLTransactionCoordinator; -class V8DatabaseCallback; class Database final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); @@ -135,7 +135,8 @@ bool PerformOpenAndVerify(bool set_version_in_new_database, DatabaseError&, String& error_message); - void RunCreationCallback(V8DatabaseCallback* creation_callback); + void RunCreationCallback( + V8PersistentCallbackFunction<V8DatabaseCallback>* creation_callback); void ScheduleTransaction();
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp b/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp index 7b525bed..36e7d5b 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp
@@ -49,7 +49,12 @@ bool SQLStatement::OnSuccessV8Impl::OnSuccess(SQLTransaction* transaction, SQLResultSet* result_set) { - return callback_->handleEvent(nullptr, transaction, result_set); + v8::TryCatch try_catch(callback_->GetIsolate()); + try_catch.SetVerbose(true); + + // An exception if any is killed with the v8::TryCatch above and reported + // to the global exception handler. + return callback_->handleEvent(nullptr, transaction, result_set).IsJust(); } void SQLStatement::OnErrorV8Impl::Trace(blink::Visitor* visitor) { @@ -59,7 +64,23 @@ bool SQLStatement::OnErrorV8Impl::OnError(SQLTransaction* transaction, SQLError* error) { - return callback_->handleEvent(nullptr, transaction, error); + v8::TryCatch try_catch(callback_->GetIsolate()); + try_catch.SetVerbose(true); + + // 4.3.2 Processing model + // https://www.w3.org/TR/webdatabase/#sqlstatementcallback + // step 6.(In case of error).2. If the error callback returns false, then move + // on to the next statement, if any, or onto the next overall step otherwise. + // step 6.(In case of error).3. Otherwise, the error callback did not return + // false, or there was no error callback. Jump to the last step in the overall + // steps. + bool return_value; + // An exception if any is killed with the v8::TryCatch above and reported + // to the global exception handler. + if (!callback_->handleEvent(nullptr, transaction, error).To(&return_value)) { + return true; + } + return return_value; } SQLStatement* SQLStatement::Create(Database* database,
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLStatementCallback.idl b/third_party/WebKit/Source/modules/webdatabase/SQLStatementCallback.idl index 77faa0e..177ca60 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLStatementCallback.idl +++ b/third_party/WebKit/Source/modules/webdatabase/SQLStatementCallback.idl
@@ -28,5 +28,5 @@ // https://www.w3.org/TR/webdatabase/#sqlstatementcallback callback interface SQLStatementCallback { - boolean handleEvent(SQLTransaction transaction, SQLResultSet resultSet); + void handleEvent(SQLTransaction transaction, SQLResultSet resultSet); };
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLStatementErrorCallback.idl b/third_party/WebKit/Source/modules/webdatabase/SQLStatementErrorCallback.idl index 8feb6bd..0c39547 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLStatementErrorCallback.idl +++ b/third_party/WebKit/Source/modules/webdatabase/SQLStatementErrorCallback.idl
@@ -28,5 +28,5 @@ // https://www.w3.org/TR/webdatabase/#sqlstatementerrorcallback callback interface SQLStatementErrorCallback { - [Custom] boolean handleEvent(SQLTransaction transaction, SQLError error); + boolean handleEvent(SQLTransaction transaction, SQLError error); };
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp b/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp index abf35af..c3a3e72 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp
@@ -53,7 +53,12 @@ } bool SQLTransaction::OnProcessV8Impl::OnProcess(SQLTransaction* transaction) { - return callback_->handleEvent(nullptr, transaction); + v8::TryCatch try_catch(callback_->GetIsolate()); + try_catch.SetVerbose(true); + + // An exception if any is killed with the v8::TryCatch above and reported + // to the global exception handler. + return callback_->handleEvent(nullptr, transaction).IsJust(); } void SQLTransaction::OnSuccessV8Impl::Trace(blink::Visitor* visitor) { @@ -71,7 +76,12 @@ } bool SQLTransaction::OnErrorV8Impl::OnError(SQLError* error) { - return callback_->handleEvent(nullptr, error); + v8::TryCatch try_catch(callback_->GetIsolate()); + try_catch.SetVerbose(true); + + // An exception if any is killed with the v8::TryCatch above and reported + // to the global exception handler. + return callback_->handleEvent(nullptr, error).IsJust(); } SQLTransaction* SQLTransaction::Create(Database* db,
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCallback.idl b/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCallback.idl index 450267b..60d9bb1 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCallback.idl +++ b/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCallback.idl
@@ -28,5 +28,5 @@ // https://www.w3.org/TR/webdatabase/#sqltransactioncallback callback interface SQLTransactionCallback { - boolean handleEvent(SQLTransaction transaction); + void handleEvent(SQLTransaction transaction); };
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLTransactionErrorCallback.idl b/third_party/WebKit/Source/modules/webdatabase/SQLTransactionErrorCallback.idl index 396ada4de..d81c6e5 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLTransactionErrorCallback.idl +++ b/third_party/WebKit/Source/modules/webdatabase/SQLTransactionErrorCallback.idl
@@ -28,5 +28,5 @@ // https://www.w3.org/TR/webdatabase/#sqltransactionerrorcallback callback interface SQLTransactionErrorCallback { - boolean handleEvent(SQLError error); + void handleEvent(SQLError error); };
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index dc9e480..e9fd7b6e 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -618,7 +618,6 @@ "exported/WebAudioDevice.cpp", "exported/WebBlobInfo.cpp", "exported/WebCORS.cpp", - "exported/WebCORSPreflightResultCache.cpp", "exported/WebCache.cpp", "exported/WebCanvasCaptureHandler.cpp", "exported/WebClipboardImpl.cpp", @@ -1811,7 +1810,6 @@ "audio/VectorMathTest.cpp", "bindings/RuntimeCallStatsTest.cpp", "exported/FilePathConversionTest.cpp", - "exported/WebCORSPreflightResultCacheTest.cpp", "exported/WebCORSTest.cpp", "exported/WebStringTest.cpp", "feature_policy/FeaturePolicyTest.cpp",
diff --git a/third_party/WebKit/Source/platform/PlatformExport.h b/third_party/WebKit/Source/platform/PlatformExport.h index 56faf4b..d6bb89d 100644 --- a/third_party/WebKit/Source/platform/PlatformExport.h +++ b/third_party/WebKit/Source/platform/PlatformExport.h
@@ -28,28 +28,90 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// This header defines the following macros to export component's symbols. +// +// - PLATFORM_EXPORT +// Exports non-template symbols. +// +// - PLATFORM_TEMPLATE_CLASS_EXPORT +// Exports an entire definition of class template. +// +// - PLATFORM_EXTERN_TEMPLATE_EXPORT +// Applicable to template declarations (except for definitions). The +// corresponding definition must come along with PLATFORM_TEMPLATE_EXPORT. +// Template specialization uses this macro to declare that such a +// specialization exists without providing an actual definition. +// +// - PLATFORM_TEMPLATE_EXPORT +// Applicable to template definitions whose declarations are annotated +// with PLATFORM_EXTERN_TEMPLATE_EXPORT. Template specialization uses this +// macro to provide an actual definition. + #ifndef PlatformExport_h #define PlatformExport_h +#include "build/build_config.h" + +// +// BLINK_PLATFORM_IMPLEMENTATION +// #if !defined(BLINK_PLATFORM_IMPLEMENTATION) #define BLINK_PLATFORM_IMPLEMENTATION 0 #endif -#if defined(COMPONENT_BUILD) -#if defined(WIN32) +// +// PLATFORM_EXPORT +// +#if !defined(COMPONENT_BUILD) +#define PLATFORM_EXPORT // No need of export +#else + +#if defined(COMPILER_MSVC) #if BLINK_PLATFORM_IMPLEMENTATION #define PLATFORM_EXPORT __declspec(dllexport) #else #define PLATFORM_EXPORT __declspec(dllimport) #endif -#else // defined(WIN32) +#endif // defined(COMPILER_MSVC) + +#if defined(COMPILER_GCC) +#if BLINK_PLATFORM_IMPLEMENTATION #define PLATFORM_EXPORT __attribute__((visibility("default"))) -#endif -#else // defined(COMPONENT_BUILD) +#else #define PLATFORM_EXPORT #endif +#endif // defined(COMPILER_GCC) -#if defined(_MSC_VER) +#endif // !defined(COMPONENT_BUILD) + +// +// PLATFORM_TEMPLATE_CLASS_EXPORT +// PLATFORM_EXTERN_TEMPLATE_EXPORT +// PLATFORM_TEMPLATE_EXPORT +// +#if BLINK_PLATFORM_IMPLEMENTATION + +#if defined(COMPILER_MSVC) +#define PLATFORM_TEMPLATE_CLASS_EXPORT +#define PLATFORM_EXTERN_TEMPLATE_EXPORT PLATFORM_EXPORT +#define PLATFORM_TEMPLATE_EXPORT PLATFORM_EXPORT +#endif + +#if defined(COMPILER_GCC) +#define PLATFORM_TEMPLATE_CLASS_EXPORT PLATFORM_EXPORT +#define PLATFORM_EXTERN_TEMPLATE_EXPORT PLATFORM_EXPORT +#define PLATFORM_TEMPLATE_EXPORT +#endif + +#else // BLINK_PLATFORM_IMPLEMENTATION + +#define PLATFORM_TEMPLATE_CLASS_EXPORT +#define PLATFORM_EXTERN_TEMPLATE_EXPORT PLATFORM_EXPORT +#define PLATFORM_TEMPLATE_EXPORT + +#endif // BLINK_PLATFORM_IMPLEMENTATION + +#if defined(COMPILER_MSVC) // MSVC Compiler warning C4275: // non dll-interface class 'Bar' used as base for dll-interface class 'Foo'. // Note that this is intended to be used only when no access to the base class'
diff --git a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.cpp b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.cpp index 3c866f6..810224e 100644 --- a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.cpp +++ b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.cpp
@@ -18,14 +18,20 @@ incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext()); } -CallbackFunctionBase::CallbackFunctionBase(const CallbackFunctionBase& other) - : callback_function_(other.GetIsolate(), other.CallbackFunction()), - callback_relevant_script_state_(other.callback_relevant_script_state_), - incumbent_script_state_(other.incumbent_script_state_) {} - void CallbackFunctionBase::TraceWrappers( const ScriptWrappableVisitor* visitor) const { visitor->TraceWrappers(callback_function_); } +V8PersistentCallbackFunctionBase::V8PersistentCallbackFunctionBase( + CallbackFunctionBase* callback_function) + : callback_function_(callback_function) { + v8_function_.Reset(callback_function_->GetIsolate(), + callback_function_->callback_function_.Get()); +} + +void V8PersistentCallbackFunctionBase::Trace(blink::Visitor* visitor) { + visitor->Trace(callback_function_); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h index 13dd15e..e589933 100644 --- a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h +++ b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
@@ -12,8 +12,7 @@ namespace blink { -template <typename V8CallbackFunction> -class V8PersistentCallbackFunction; +class V8PersistentCallbackFunctionBase; // CallbackFunctionBase is the common base class of all the callback function // classes. Most importantly this class provides a way of type dispatching (e.g. @@ -42,7 +41,6 @@ protected: explicit CallbackFunctionBase(v8::Local<v8::Function>); - explicit CallbackFunctionBase(const CallbackFunctionBase& other); v8::Local<v8::Function> CallbackFunction() const { return callback_function_.NewLocal(GetIsolate()); @@ -50,9 +48,6 @@ ScriptState* IncumbentScriptState() { return incumbent_script_state_.get(); } private: - template <typename V8CallbackFunction> - friend class V8PersistentCallbackFunction; - // The "callback function type" value. TraceWrapperV8Reference<v8::Function> callback_function_; // The associated Realm of the callback function type value. @@ -61,43 +56,72 @@ // converted to an IDL value. // https://heycam.github.io/webidl/#dfn-callback-context scoped_refptr<ScriptState> incumbent_script_state_; + + friend class V8PersistentCallbackFunctionBase; }; -// V8PersistentCallbackFunction retains the underlying v8::Function of a -// V8CallbackFunction, which must be a subclass of CallbackFunctionBase, without -// wrapper-tracing. This class is necessary and useful where wrapper-tracing is -// not suitable. Remember that, as a nature of v8::Persistent, abuse of -// V8PersistentCallbackFunction would result in memory leak, so the use of -// V8PersistentCallbackFunction should be limited to those which are guaranteed -// to release the persistents in a finite time period. -template <typename V8CallbackFunction> -class V8PersistentCallbackFunction final : public V8CallbackFunction { +// V8PersistentCallbackFunctionBase retains the underlying v8::Function of a +// CallbackFunctionBase without wrapper-tracing. This class is necessary and +// useful where wrapper-tracing is not suitable. Remember that, as a nature of +// v8::Persistent, abuse of V8PersistentCallbackFunctionBase would result in +// memory leak, so the use of V8PersistentCallbackFunctionBase should be limited +// to those which are guaranteed to release the persistents in a finite time +// period. +class PLATFORM_EXPORT V8PersistentCallbackFunctionBase + : public GarbageCollectedFinalized<V8PersistentCallbackFunctionBase> { public: - static V8PersistentCallbackFunction* Create( - V8CallbackFunction* callback_function) { - return callback_function - ? new V8PersistentCallbackFunction(callback_function) - : nullptr; - } + virtual ~V8PersistentCallbackFunctionBase() { v8_function_.Reset(); } - ~V8PersistentCallbackFunction() override { v8_function_.Reset(); } + virtual void Trace(blink::Visitor*); + + protected: + explicit V8PersistentCallbackFunctionBase(CallbackFunctionBase*); + + template <typename V8CallbackFunction> + V8CallbackFunction* As() { + static_assert( + std::is_base_of<CallbackFunctionBase, V8CallbackFunction>::value, + "V8CallbackFunction must be a subclass of CallbackFunctionBase."); + return static_cast<V8CallbackFunction*>(callback_function_.Get()); + } private: - explicit V8PersistentCallbackFunction(V8CallbackFunction* callback_function) - : V8CallbackFunction(*callback_function) { - v8_function_.Reset(this->GetIsolate(), this->callback_function_.Get()); - } - + Member<CallbackFunctionBase> callback_function_; v8::Persistent<v8::Function> v8_function_; }; -// TODO(yukishiino): Remove WrapPersistentCallbackFunction. -// blink::WrapPersistent + V8PersistentCallbackFunction is preferred. -template <typename T> -auto WrapPersistentCallbackFunction(T* value) { - return WrapPersistent(V8PersistentCallbackFunction<T>::Create(value)); +// V8PersistentCallbackFunction<V8CallbackFunction> is a counter-part of +// V8CallbackFunction. While V8CallbackFunction uses wrapper-tracing, +// V8PersistentCallbackFunction<V8CallbackFunction> uses v8::Persistent to make +// the underlying v8::Function alive. +// +// Since the signature of |Invoke| varies depending on the IDL definition, +// the class definition is specialized and generated by the bindings code +// generator. +template <typename V8CallbackFunction> +class V8PersistentCallbackFunction; + +// Converts the wrapper-tracing version of a callback function to the +// v8::Persistent version of it. +template <typename V8CallbackFunction> +inline V8PersistentCallbackFunction<V8CallbackFunction>* +ToV8PersistentCallbackFunction(V8CallbackFunction* callback_function) { + static_assert( + std::is_base_of<CallbackFunctionBase, V8CallbackFunction>::value, + "V8CallbackFunction must be a subclass of CallbackFunctionBase."); + return callback_function + ? new V8PersistentCallbackFunction<V8CallbackFunction>( + callback_function) + : nullptr; } +// CallbackFunctionBase is designed to be used with wrapper-tracing. As +// blink::Persistent does not perform wrapper-tracing, use of |WrapPersistent| +// for callback functions is likely (if not always) misuse. Thus, this code +// prohibits such a use case. The call sites should explicitly use +// WrapPersistent(V8PersistentCallbackFunction<T>*). +Persistent<CallbackFunctionBase> WrapPersistent(CallbackFunctionBase*) = delete; + } // namespace blink #endif // CallbackFunctionBase_h
diff --git a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp b/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp deleted file mode 100644 index 37ef62e..0000000 --- a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp +++ /dev/null
@@ -1,184 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple 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 COMPUTER, INC. ``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 COMPUTER, INC. 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 "public/platform/WebCORSPreflightResultCache.h" - -#include <memory> -#include "base/time/default_tick_clock.h" -#include "base/time/tick_clock.h" -#include "net/http/http_request_headers.h" -#include "platform/loader/cors/CORS.h" -#include "platform/loader/cors/CORSErrorString.h" -#include "platform/loader/fetch/FetchUtils.h" -#include "platform/loader/fetch/ResourceResponse.h" -#include "platform/network/http_names.h" -#include "platform/wtf/StdLibExtras.h" -#include "platform/wtf/ThreadSpecific.h" -#include "platform/wtf/Time.h" -#include "public/platform/WebCORS.h" - -namespace blink { - -namespace { - -base::Optional<std::string> GetOptionalHeaderValue( - const WebHTTPHeaderMap& header_map, - const AtomicString& header_name) { - const AtomicString& result = header_map.Get(header_name); - if (result.IsNull()) - return base::nullopt; - - return std::string(result.Ascii().data(), result.Ascii().length()); -} - -std::unique_ptr<net::HttpRequestHeaders> CreateNetHttpRequestHeaders( - const WebHTTPHeaderMap& header_map) { - std::unique_ptr<net::HttpRequestHeaders> request_headers = - std::make_unique<net::HttpRequestHeaders>(); - for (const auto& header : header_map.GetHTTPHeaderMap()) { - // TODO(toyoshim): Use CHECK() for a while to ensure that these assumptions - // are correct. Should be changed to DCHECK before the next branch cut. - CHECK(!header.key.IsNull()); - CHECK(!header.value.IsNull()); - request_headers->SetHeader( - std::string(header.key.Ascii().data(), header.key.Ascii().length()), - std::string(header.value.Ascii().data(), - header.value.Ascii().length())); - } - return request_headers; -} - -} // namespace - -WebCORSPreflightResultCache& WebCORSPreflightResultCache::Shared() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<WebCORSPreflightResultCache>, - cache, ()); - return *cache; -} - -WebCORSPreflightResultCache::WebCORSPreflightResultCache() = default; -WebCORSPreflightResultCache::~WebCORSPreflightResultCache() = default; - -bool WebCORSPreflightResultCache::EnsureResultAndMayAppendEntry( - const WebHTTPHeaderMap& response_header_map, - const WebString& origin, - const WebURL& request_url, - const WebString& request_method, - const WebHTTPHeaderMap& request_header_map, - network::mojom::FetchCredentialsMode request_credentials_mode, - WebString* error_description) { - DCHECK(error_description); - - base::Optional<network::mojom::CORSError> error; - - std::unique_ptr<network::cors::PreflightResult> result = - network::cors::PreflightResult::Create( - request_credentials_mode, - GetOptionalHeaderValue(response_header_map, - HTTPNames::Access_Control_Allow_Methods), - GetOptionalHeaderValue(response_header_map, - HTTPNames::Access_Control_Allow_Headers), - GetOptionalHeaderValue(response_header_map, - HTTPNames::Access_Control_Max_Age), - &error); - if (error) { - *error_description = CORS::GetErrorString( - CORS::ErrorParameter::CreateForPreflightResponseCheck(*error, - String())); - return false; - } - - DCHECK(!request_method.IsNull()); - error = result->EnsureAllowedCrossOriginMethod(std::string( - request_method.Ascii().data(), request_method.Ascii().length())); - if (error) { - *error_description = CORS::GetErrorString( - CORS::ErrorParameter::CreateForPreflightResponseCheck(*error, - request_method)); - return false; - } - - std::string detected_error_header; - error = result->EnsureAllowedCrossOriginHeaders( - *CreateNetHttpRequestHeaders(request_header_map), &detected_error_header); - if (error) { - *error_description = CORS::GetErrorString( - CORS::ErrorParameter::CreateForPreflightResponseCheck( - *error, String(detected_error_header.data(), - detected_error_header.length()))); - return false; - } - - DCHECK(!error); - AppendEntry(origin, request_url, std::move(result)); - return true; -} - -void WebCORSPreflightResultCache::AppendEntry( - const WebString& web_origin, - const WebURL& web_url, - std::unique_ptr<network::cors::PreflightResult> preflight_result) { - std::string url(web_url.GetString().Ascii()); - std::string origin(web_origin.Ascii()); - - preflight_hash_map_[origin][url] = std::move(preflight_result); -} - -bool WebCORSPreflightResultCache::CanSkipPreflight( - const WebString& web_origin, - const WebURL& web_url, - network::mojom::FetchCredentialsMode credentials_mode, - const WebString& method, - const WebHTTPHeaderMap& request_headers) { - std::string origin(web_origin.Ascii()); - std::string url(web_url.GetString().Ascii()); - - // either origin or url not in cache: - if (preflight_hash_map_.find(origin) == preflight_hash_map_.end() || - preflight_hash_map_[origin].find(url) == - preflight_hash_map_[origin].end()) { - return false; - } - - // both origin and url in cache -> check if still valid and if sufficient to - // skip redirect: - DCHECK(!method.IsNull()); - if (preflight_hash_map_[origin][url]->EnsureAllowedRequest( - credentials_mode, - std::string(method.Ascii().data(), method.Ascii().length()), - *CreateNetHttpRequestHeaders(request_headers))) { - return true; - } - - // Either cache entry is stale or not sufficient. Remove item from cache: - preflight_hash_map_[origin].erase(url); - if (preflight_hash_map_[origin].empty()) - preflight_hash_map_.erase(origin); - - return false; -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp b/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp deleted file mode 100644 index c224a88..0000000 --- a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp +++ /dev/null
@@ -1,266 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "public/platform/WebCORSPreflightResultCache.h" - -#include "base/strings/stringprintf.h" -#include "base/test/simple_test_tick_clock.h" -#include "platform/network/HTTPHeaderMap.h" -#include "platform/testing/URLTestHelpers.h" -#include "platform/weborigin/KURL.h" -#include "platform/wtf/Time.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { - -namespace test { - -class TestWebCORSPreflightResultCache : public WebCORSPreflightResultCache { - public: - TestWebCORSPreflightResultCache() = default; - ~TestWebCORSPreflightResultCache() override = default; - - // Counts origins and urls in the cache. Thus with a single cache item, this - // method would return 2. This is to tests whether we clean up the references - // on all levels. - int CacheSize() { - int size = 0; - - for (auto const& origin : preflight_hash_map_) { - size++; - for (auto const& url : origin.second) { - (void)url; // Prevents unused compile error. - size++; - } - } - - return size; - } -}; - -} // namespace test - -class WebCORSPreflightResultCacheTest : public ::testing::Test { - protected: - base::SimpleTestTickClock* clock() { return &clock_; } - - // This is by no means a robust parser and works only for the headers strings - // used in this tests. - HTTPHeaderMap ParseHeaderString(const std::string& headers) { - HTTPHeaderMap header_map; - std::stringstream stream; - stream.str(headers); - std::string line; - while (std::getline(stream, line, ';')) { - int colon = line.find_first_of(':'); - - header_map.Add( - AtomicString::FromUTF8(line.substr(0, colon).data()), - AtomicString::FromUTF8(line.substr(colon + 1, line.size()).data())); - } - - return header_map; - } - - private: - base::SimpleTestTickClock clock_; -}; - -TEST_F(WebCORSPreflightResultCacheTest, CacheTimeout) { - WebString origin("null"); - WebURL url = URLTestHelpers::ToKURL("http://www.test.com/A"); - WebURL other_url = URLTestHelpers::ToKURL("http://www.test.com/B"); - - test::TestWebCORSPreflightResultCache cache; - network::cors::PreflightResult::SetTickClockForTesting(clock()); - - // Cache should be empty: - EXPECT_EQ(0, cache.CacheSize()); - - cache.AppendEntry( - origin, url, - network::cors::PreflightResult::Create( - network::mojom::FetchCredentialsMode::kInclude, std::string("POST"), - base::nullopt, std::string("5"), nullptr)); - cache.AppendEntry( - origin, other_url, - network::cors::PreflightResult::Create( - network::mojom::FetchCredentialsMode::kInclude, std::string("POST"), - base::nullopt, std::string("5"), nullptr)); - - // Cache size should be 3 (counting origins and urls separately): - EXPECT_EQ(3, cache.CacheSize()); - - // Cache entry should still be valid: - EXPECT_TRUE(cache.CanSkipPreflight( - origin, url, network::mojom::FetchCredentialsMode::kInclude, "POST", - HTTPHeaderMap())); - - // Advance time by ten seconds: - clock()->Advance(TimeDelta::FromSeconds(10)); - - // Cache entry should now be expired: - EXPECT_FALSE(cache.CanSkipPreflight( - origin, url, network::mojom::FetchCredentialsMode::kInclude, "POST", - HTTPHeaderMap())); - - // Cache size should be 2, with the expired entry removed by call to - // CanSkipPreflight() but one origin and one url still in the cache: - EXPECT_EQ(2, cache.CacheSize()); - - // Cache entry should be expired: - EXPECT_FALSE(cache.CanSkipPreflight( - origin, other_url, network::mojom::FetchCredentialsMode::kInclude, "POST", - HTTPHeaderMap())); - - // Cache size should be 0, with the expired entry removed by call to - // CanSkipPreflight(): - EXPECT_EQ(0, cache.CacheSize()); - - network::cors::PreflightResult::SetTickClockForTesting(nullptr); -} - -TEST_F(WebCORSPreflightResultCacheTest, CacheSize) { - WebString origin("null"); - WebString other_origin("http://www.other.com:80"); - WebURL url = URLTestHelpers::ToKURL("http://www.test.com/A"); - WebURL other_url = URLTestHelpers::ToKURL("http://www.test.com/B"); - - test::TestWebCORSPreflightResultCache cache; - - // Cache should be empty: - EXPECT_EQ(0, cache.CacheSize()); - - cache.AppendEntry( - origin, url, - network::cors::PreflightResult::Create( - network::mojom::FetchCredentialsMode::kInclude, std::string("POST"), - base::nullopt, base::nullopt, nullptr)); - - // Cache size should be 2 (counting origins and urls separately): - EXPECT_EQ(2, cache.CacheSize()); - - cache.AppendEntry( - origin, other_url, - network::cors::PreflightResult::Create( - network::mojom::FetchCredentialsMode::kInclude, std::string("POST"), - base::nullopt, base::nullopt, nullptr)); - - // Cache size should now be 3 (1 origin, 2 urls): - EXPECT_EQ(3, cache.CacheSize()); - - cache.AppendEntry( - other_origin, url, - network::cors::PreflightResult::Create( - network::mojom::FetchCredentialsMode::kInclude, std::string("POST"), - base::nullopt, base::nullopt, nullptr)); - // Cache size should now be 4 (4 origin, 3 urls): - EXPECT_EQ(5, cache.CacheSize()); -} - -TEST_F(WebCORSPreflightResultCacheTest, CanSkipPreflight) { - const struct { - const std::string allow_methods; - const std::string allow_headers; - const network::mojom::FetchCredentialsMode cache_credentials_mode; - - const std::string request_method; - const std::string request_headers; - const network::mojom::FetchCredentialsMode request_credentials_mode; - - bool can_skip_preflight; - } tests[] = { - // Different methods: - {"OPTIONS", "", network::mojom::FetchCredentialsMode::kOmit, "OPTIONS", - "", network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET", "", network::mojom::FetchCredentialsMode::kOmit, "GET", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"HEAD", "", network::mojom::FetchCredentialsMode::kOmit, "HEAD", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"POST", "", network::mojom::FetchCredentialsMode::kOmit, "POST", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"PUT", "", network::mojom::FetchCredentialsMode::kOmit, "PUT", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"DELETE", "", network::mojom::FetchCredentialsMode::kOmit, "DELETE", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - - // Cache allowing multiple methods: - {"GET, PUT, DELETE", "", network::mojom::FetchCredentialsMode::kOmit, - "GET", "", network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET, PUT, DELETE", "", network::mojom::FetchCredentialsMode::kOmit, - "PUT", "", network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET, PUT, DELETE", "", network::mojom::FetchCredentialsMode::kOmit, - "DELETE", "", network::mojom::FetchCredentialsMode::kOmit, true}, - - // Methods not in cached preflight response: - {"GET", "", network::mojom::FetchCredentialsMode::kOmit, "PUT", "", - network::mojom::FetchCredentialsMode::kOmit, false}, - {"GET, POST, DELETE", "", network::mojom::FetchCredentialsMode::kOmit, - "PUT", "", network::mojom::FetchCredentialsMode::kOmit, false}, - - // Allowed headers: - {"GET", "X-MY-HEADER", network::mojom::FetchCredentialsMode::kOmit, "GET", - "X-MY-HEADER:t", network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET", "X-MY-HEADER, Y-MY-HEADER", - network::mojom::FetchCredentialsMode::kOmit, "GET", - "X-MY-HEADER:t;Y-MY-HEADER:t", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET", "x-my-header, Y-MY-HEADER", - network::mojom::FetchCredentialsMode::kOmit, "GET", - "X-MY-HEADER:t;y-my-header:t", - network::mojom::FetchCredentialsMode::kOmit, true}, - - // Requested headers not in cached preflight response: - {"GET", "", network::mojom::FetchCredentialsMode::kOmit, "GET", - "X-MY-HEADER:t", network::mojom::FetchCredentialsMode::kOmit, false}, - {"GET", "X-SOME-OTHER-HEADER", - network::mojom::FetchCredentialsMode::kOmit, "GET", "X-MY-HEADER:t", - network::mojom::FetchCredentialsMode::kOmit, false}, - {"GET", "X-MY-HEADER", network::mojom::FetchCredentialsMode::kOmit, "GET", - "X-MY-HEADER:t;Y-MY-HEADER:t", - network::mojom::FetchCredentialsMode::kOmit, false}, - - // Different credential modes: - {"GET", "", network::mojom::FetchCredentialsMode::kInclude, "GET", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET", "", network::mojom::FetchCredentialsMode::kInclude, "GET", "", - network::mojom::FetchCredentialsMode::kInclude, true}, - - // Credential mode mismatch: - {"GET", "", network::mojom::FetchCredentialsMode::kOmit, "GET", "", - network::mojom::FetchCredentialsMode::kOmit, true}, - {"GET", "", network::mojom::FetchCredentialsMode::kOmit, "GET", "", - network::mojom::FetchCredentialsMode::kInclude, false}, - }; - - for (const auto& test : tests) { - SCOPED_TRACE( - ::testing::Message() - << "allow_methods: [" << test.allow_methods << "], allow_headers: [" - << test.allow_headers << "], request_method: [" << test.request_method - << "], request_headers: [" << test.request_headers - << "] expect CanSkipPreflight() to return " << test.can_skip_preflight); - - WebString origin("null"); - WebURL url = URLTestHelpers::ToKURL("http://www.test.com/"); - - std::unique_ptr<network::cors::PreflightResult> item = - network::cors::PreflightResult::Create( - test.cache_credentials_mode, test.allow_methods, test.allow_headers, - base::nullopt, nullptr); - EXPECT_TRUE(item); - - test::TestWebCORSPreflightResultCache cache; - - cache.AppendEntry(origin, url, std::move(item)); - - EXPECT_EQ(cache.CanSkipPreflight(origin, url, test.request_credentials_mode, - String(test.request_method.data(), - test.request_method.length()), - ParseHeaderString(test.request_headers)), - test.can_skip_preflight); - } -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index c6bd2a4..73e7ec9 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -96,6 +96,7 @@ contents_visible_(true), is_root_for_isolated_group_(false), hit_testable_without_draws_content_(false), + needs_check_raster_invalidation_(false), has_scroll_parent_(false), has_clip_parent_(false), painted_(false), @@ -337,7 +338,9 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect, GraphicsContext::DisabledMode disabled_mode) { - if (!PaintWithoutCommit(interest_rect, disabled_mode)) + if (PaintWithoutCommit(interest_rect, disabled_mode)) + GetPaintController().CommitNewDisplayItems(); + else if (!needs_check_raster_invalidation_) return false; #if DCHECK_IS_ON() @@ -347,8 +350,6 @@ } #endif - GetPaintController().CommitNewDisplayItems(); - if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName(); // Generate raster invalidations for SPv175 (but not SPv2). @@ -372,6 +373,7 @@ } } + needs_check_raster_invalidation_ = false; return true; }
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h index 983510cd..fc0be96 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -293,6 +293,10 @@ // must DrawsContent. The result is never nullptr. sk_sp<PaintRecord> CapturePaintRecord() const; + void SetNeedsCheckRasterInvalidation() { + needs_check_raster_invalidation_ = true; + } + protected: String DebugName(cc::Layer*) const; bool ShouldFlattenTransform() const { return should_flatten_transform_; } @@ -378,6 +382,7 @@ bool contents_visible_ : 1; bool is_root_for_isolated_group_ : 1; bool hit_testable_without_draws_content_ : 1; + bool needs_check_raster_invalidation_ : 1; bool has_scroll_parent_ : 1; bool has_clip_parent_ : 1;
diff --git a/third_party/WebKit/Source/platform/heap/Persistent.h b/third_party/WebKit/Source/platform/heap/Persistent.h index 22f96f2..8fea884 100644 --- a/third_party/WebKit/Source/platform/heap/Persistent.h +++ b/third_party/WebKit/Source/platform/heap/Persistent.h
@@ -728,6 +728,14 @@ template <typename T> Persistent<T> WrapPersistent(T* value) { + // There is no technical need to require a complete type here. However, types + // that support wrapper-tracing are not suitable with WrapPersistent because + // Persistent<T> does not perform wrapper-tracing. We'd like to delete such + // overloads for sure. Thus, we require a complete type here so that it makes + // sure that an appropriate header is included and such an overload is + // deleted. + static_assert(sizeof(T), "T must be fully defined"); + return Persistent<T>(value); }
diff --git a/third_party/WebKit/Source/platform/loader/cors/CORS.cpp b/third_party/WebKit/Source/platform/loader/cors/CORS.cpp index c1161cfa..97f4cd16 100644 --- a/third_party/WebKit/Source/platform/loader/cors/CORS.cpp +++ b/third_party/WebKit/Source/platform/loader/cors/CORS.cpp
@@ -6,14 +6,17 @@ #include <string> +#include "platform/loader/cors/CORSErrorString.h" #include "platform/network/HTTPHeaderMap.h" #include "platform/network/http_names.h" #include "platform/runtime_enabled_features.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SchemeRegistry.h" #include "platform/weborigin/SecurityOrigin.h" +#include "platform/wtf/ThreadSpecific.h" #include "platform/wtf/text/AtomicString.h" #include "services/network/public/cpp/cors/cors.h" +#include "services/network/public/cpp/cors/preflight_cache.h" #include "url/gurl.h" namespace blink { @@ -30,6 +33,37 @@ return base::nullopt; } +network::cors::PreflightCache& GetPerThreadPreflightCache() { + DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<network::cors::PreflightCache>, + cache, ()); + return *cache; +} + +base::Optional<std::string> GetOptionalHeaderValue( + const HTTPHeaderMap& header_map, + const AtomicString& header_name) { + const AtomicString& result = header_map.Get(header_name); + if (result.IsNull()) + return base::nullopt; + + return std::string(result.Ascii().data()); +} + +std::unique_ptr<net::HttpRequestHeaders> CreateNetHttpRequestHeaders( + const HTTPHeaderMap& header_map) { + std::unique_ptr<net::HttpRequestHeaders> request_headers = + std::make_unique<net::HttpRequestHeaders>(); + for (HTTPHeaderMap::const_iterator i = header_map.begin(), + end = header_map.end(); + i != end; ++i) { + DCHECK(!i->key.IsNull()); + DCHECK(!i->value.IsNull()); + request_headers->SetHeader(std::string(i->key.Ascii().data()), + std::string(i->value.Ascii().data())); + } + return request_headers; +} + } // namespace namespace CORS { @@ -77,6 +111,79 @@ return network::cors::IsCORSEnabledRequestMode(request_mode); } +bool EnsurePreflightResultAndCacheOnSuccess( + const HTTPHeaderMap& response_header_map, + const String& origin, + const KURL& request_url, + const String& request_method, + const HTTPHeaderMap& request_header_map, + network::mojom::FetchCredentialsMode request_credentials_mode, + String* error_description) { + DCHECK(!origin.IsNull()); + DCHECK(!request_method.IsNull()); + DCHECK(error_description); + + base::Optional<network::mojom::CORSError> error; + + std::unique_ptr<network::cors::PreflightResult> result = + network::cors::PreflightResult::Create( + request_credentials_mode, + GetOptionalHeaderValue(response_header_map, + HTTPNames::Access_Control_Allow_Methods), + GetOptionalHeaderValue(response_header_map, + HTTPNames::Access_Control_Allow_Headers), + GetOptionalHeaderValue(response_header_map, + HTTPNames::Access_Control_Max_Age), + &error); + if (error) { + *error_description = CORS::GetErrorString( + CORS::ErrorParameter::CreateForPreflightResponseCheck(*error, + String())); + return false; + } + + error = result->EnsureAllowedCrossOriginMethod( + std::string(request_method.Ascii().data())); + if (error) { + *error_description = CORS::GetErrorString( + CORS::ErrorParameter::CreateForPreflightResponseCheck(*error, + request_method)); + return false; + } + + std::string detected_error_header; + error = result->EnsureAllowedCrossOriginHeaders( + *CreateNetHttpRequestHeaders(request_header_map), &detected_error_header); + if (error) { + *error_description = CORS::GetErrorString( + CORS::ErrorParameter::CreateForPreflightResponseCheck( + *error, String(detected_error_header.data(), + detected_error_header.length()))); + return false; + } + + DCHECK(!error); + + GetPerThreadPreflightCache().AppendEntry(std::string(origin.Ascii().data()), + request_url, std::move(result)); + return true; +} + +bool CheckIfRequestCanSkipPreflight( + const String& origin, + const KURL& url, + network::mojom::FetchCredentialsMode credentials_mode, + const String& method, + const HTTPHeaderMap& request_header_map) { + DCHECK(!origin.IsNull()); + DCHECK(!method.IsNull()); + + return GetPerThreadPreflightCache().CheckIfRequestCanSkipPreflight( + std::string(origin.Ascii().data()), url, credentials_mode, + std::string(method.Ascii().data()), + *CreateNetHttpRequestHeaders(request_header_map)); +} + bool IsCORSSafelistedMethod(const String& method) { DCHECK(!method.IsNull()); CString utf8_method = method.Utf8();
diff --git a/third_party/WebKit/Source/platform/loader/cors/CORS.h b/third_party/WebKit/Source/platform/loader/cors/CORS.h index c235858..e915ef2 100644 --- a/third_party/WebKit/Source/platform/loader/cors/CORS.h +++ b/third_party/WebKit/Source/platform/loader/cors/CORS.h
@@ -41,6 +41,22 @@ PLATFORM_EXPORT bool IsCORSEnabledRequestMode(network::mojom::FetchRequestMode); +PLATFORM_EXPORT bool EnsurePreflightResultAndCacheOnSuccess( + const HTTPHeaderMap& response_header_map, + const String& origin, + const KURL& request_url, + const String& request_method, + const HTTPHeaderMap& request_header_map, + network::mojom::FetchCredentialsMode request_credentials_mode, + String* error_description); + +PLATFORM_EXPORT bool CheckIfRequestCanSkipPreflight( + const String& origin, + const KURL&, + network::mojom::FetchCredentialsMode, + const String& method, + const HTTPHeaderMap& request_header_map); + // Thin wrapper functions that will not be removed even after out-of-renderer // CORS is enabled. PLATFORM_EXPORT bool IsCORSSafelistedMethod(const String& method);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp index a44ed3c..b7fdd9a 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.cpp
@@ -95,7 +95,8 @@ int64_t, bool) {} -void FetchContext::DispatchDidFail(unsigned long, +void FetchContext::DispatchDidFail(const KURL&, + unsigned long, const ResourceError&, int64_t, bool) {}
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h index a26ab2e..c6f2dc7a 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h +++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
@@ -153,7 +153,8 @@ int64_t encoded_data_length, int64_t decoded_body_length, bool blocked_cross_site_document); - virtual void DispatchDidFail(unsigned long identifier, + virtual void DispatchDidFail(const KURL&, + unsigned long identifier, const ResourceError&, int64_t encoded_data_length, bool is_internal_request);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp index 88e3f2f..ea436d8 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -1460,9 +1460,9 @@ FetchInitiatorTypeNames::internal; resource->VirtualTimePauser().PauseVirtualTime(false); - Context().DispatchDidFail(resource->Identifier(), error, - resource->GetResponse().EncodedDataLength(), - is_internal_request); + Context().DispatchDidFail( + resource->LastResourceRequest().Url(), resource->Identifier(), error, + resource->GetResponse().EncodedDataLength(), is_internal_request); if (error.IsCancellation()) RemovePreload(resource);
diff --git a/third_party/WebKit/Source/platform/network/NetworkUtils.cpp b/third_party/WebKit/Source/platform/network/NetworkUtils.cpp index d6b6fbe..1b81e68 100644 --- a/third_party/WebKit/Source/platform/network/NetworkUtils.cpp +++ b/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
@@ -123,6 +123,10 @@ return error_code == net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED; } +bool IsLegacySymantecCertError(int error_code) { + return error_code == net::ERR_CERT_SYMANTEC_LEGACY; +} + } // NetworkUtils } // namespace blink
diff --git a/third_party/WebKit/Source/platform/network/NetworkUtils.h b/third_party/WebKit/Source/platform/network/NetworkUtils.h index 5f0f1ede..19118d0 100644 --- a/third_party/WebKit/Source/platform/network/NetworkUtils.h +++ b/third_party/WebKit/Source/platform/network/NetworkUtils.h
@@ -42,6 +42,8 @@ PLATFORM_EXPORT bool IsCertificateTransparencyRequiredError(int); +PLATFORM_EXPORT bool IsLegacySymantecCertError(int); + } // NetworkUtils } // namespace blink
diff --git a/third_party/WebKit/public/mojom/service_worker/service_worker.mojom b/third_party/WebKit/public/mojom/service_worker/service_worker.mojom index ea842bf..0733dd10 100644 --- a/third_party/WebKit/public/mojom/service_worker/service_worker.mojom +++ b/third_party/WebKit/public/mojom/service_worker/service_worker.mojom
@@ -26,25 +26,32 @@ => (array<ServiceWorkerClientInfo> clients); // Corresponds to Clients#get(id). Gets information of the service worker - // client with |client_uuid|. - GetClient(string client_uuid) => (ServiceWorkerClientInfo client); + // client with |client_uuid|. |client| is null if it was not found or is not + // same-origin with this service worker. + GetClient(string client_uuid) => (ServiceWorkerClientInfo? client); // Corresponds to Clients#openWindow(url). Requests the browser to open a tab // with |url|. - // On success, |client| contains service worker client information of the - // newly opened window and |error_msg| is null. - // Otherwise, |client| is null and |error_msg| describes the failure. + // If the tab was successfully opened, |success| is true. |client| contains + // information about the newly opened window, but may be null if that + // information could not be obtained (this can happen for a cross-origin + // window, or if the browser process could not get the information in time + // before the window was closed). + // If |success| is false, |error_msg| describes the failure. OpenNewTab(url.mojom.Url url) - => (ServiceWorkerClientInfo? client, string? error_msg); + => (bool success, ServiceWorkerClientInfo? client, string? error_msg); // Corresponds to PaymentRequestEvent#openWindow(url). // Spec: https://w3c.github.io/payment-handler/#openwindow-method // Requests the browser to open a payment handler window with |url|. - // On success, |client| contains service worker client information of the - // newly opened window and |error_msg| is null. - // Otherwise, |client| is null and |error_msg| describes the failure. + // If the window was successfully opened, |success| is true. |client| contains + // information about the newly opened window, but may be null if that + // information could not be obtained (this can happen for a cross-origin + // window, or if the browser process could not get the information in time + // before the window was closed). + // If |success| is false, |error_msg| describes the failure. OpenPaymentHandlerWindow(url.mojom.Url url) - => (ServiceWorkerClientInfo? client, string? error_msg); + => (bool success, ServiceWorkerClientInfo? client, string? error_msg); // TODO(leonhsl): Impl all methods. // PostMessageToClient(); @@ -58,11 +65,14 @@ // Corresponds to WindowClient#navigate(). Requests the browser to navigate // the client with |client_uuid| to |url|. - // On success, |client| contains service worker client information of the - // navigated window and |error_msg| is null. - // Otherwise, |client| is null and |error_msg| describes the failure. + // If the navigation was successful, |success| is true. |client| contains + // information about the navigated window, but may be null if that + // information could not be obtained (this can happen for a cross-origin + // window, or if the browser process could not get the information in time + // before the window was closed). + // If |success| is false, |error_msg| describes the failure. NavigateClient(string client_uuid, url.mojom.Url url) - => (ServiceWorkerClientInfo? client, string? error_msg); + => (bool success, ServiceWorkerClientInfo? client, string? error_msg); // Corresponds to ServiceWorkerGlobalScope#skipWaiting(). Allows this service // worker to progress from the registration's waiting position to active even
diff --git a/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h b/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h deleted file mode 100644 index 51b129d..0000000 --- a/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h +++ /dev/null
@@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 Apple 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 COMPUTER, INC. ``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 COMPUTER, INC. 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 WebCORSPreflightResultCache_h -#define WebCORSPreflightResultCache_h - -#include <memory> -#include <string> -#include "base/containers/flat_set.h" -#include "base/time/time.h" -#include "platform/loader/fetch/ResourceLoaderOptions.h" -#include "public/platform/WebHTTPHeaderMap.h" -#include "public/platform/WebHTTPHeaderSet.h" -#include "public/platform/WebString.h" -#include "public/platform/WebURL.h" -#include "public/platform/WebURLRequest.h" -#include "public/platform/WebURLResponse.h" -#include "services/network/public/cpp/cors/preflight_result.h" - -namespace blink { - -class BLINK_PLATFORM_EXPORT WebCORSPreflightResultCache { - public: - WebCORSPreflightResultCache(const WebCORSPreflightResultCache&) = delete; - WebCORSPreflightResultCache& operator=(const WebCORSPreflightResultCache&) = - delete; - - // Returns a WebCORSPreflightResultCache which is shared in the same thread. - static WebCORSPreflightResultCache& Shared(); - - // TODO(toyoshim): Move to platform/loader/cors, as - // CORS::EnsurePreflightResultAndCacheOnSuccess when - // WebCORSPreflightResultCache is ported to network service. - bool EnsureResultAndMayAppendEntry( - const WebHTTPHeaderMap& response_header_map, - const WebString& origin, - const WebURL& request_url, - const WebString& request_method, - const WebHTTPHeaderMap& request_header_map, - network::mojom::FetchCredentialsMode request_credentials_mode, - WebString* error_description); - - // TODO(toyoshim): Remove the following method that is used only for testing - // outside this class implementation. - void AppendEntry(const WebString& origin, - const WebURL&, - std::unique_ptr<network::cors::PreflightResult>); - - // TODO(toyoshim): Move to platform/loader/cors, as CORS::CanSkipPreflight - // when WebCORSPreflightResultCache is ported to network service. - bool CanSkipPreflight(const WebString& origin, - const WebURL&, - network::mojom::FetchCredentialsMode, - const WebString& method, - const WebHTTPHeaderMap& request_headers); - - protected: - friend class WTF::ThreadSpecific<WebCORSPreflightResultCache>; - - WebCORSPreflightResultCache(); - virtual ~WebCORSPreflightResultCache(); - - typedef std::map< - std::string, - std::map<std::string, std::unique_ptr<network::cors::PreflightResult>>> - PreflightResultHashMap; - - PreflightResultHashMap preflight_hash_map_; -}; - -} // namespace blink - -#endif
diff --git a/third_party/mt19937ar/BUILD.gn b/third_party/mt19937ar/BUILD.gn deleted file mode 100644 index 35c2d9b3..0000000 --- a/third_party/mt19937ar/BUILD.gn +++ /dev/null
@@ -1,10 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -static_library("mt19937ar") { - sources = [ - "mt19937ar.cc", - "mt19937ar.h", - ] -}
diff --git a/third_party/mt19937ar/DEPS b/third_party/mt19937ar/DEPS deleted file mode 100644 index b931410..0000000 --- a/third_party/mt19937ar/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - '+base', -] \ No newline at end of file
diff --git a/third_party/mt19937ar/LICENSE b/third_party/mt19937ar/LICENSE deleted file mode 100644 index ad6051b4..0000000 --- a/third_party/mt19937ar/LICENSE +++ /dev/null
@@ -1,35 +0,0 @@ - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - 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. - - 3. The names of its contributors may not 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.
diff --git a/third_party/mt19937ar/OWNERS b/third_party/mt19937ar/OWNERS deleted file mode 100644 index 3dc913a..0000000 --- a/third_party/mt19937ar/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -asvitkine@chromium.org - -# COMPONENT: Internals>Metrics
diff --git a/third_party/mt19937ar/README.chromium b/third_party/mt19937ar/README.chromium deleted file mode 100644 index 75cf4bcb9..0000000 --- a/third_party/mt19937ar/README.chromium +++ /dev/null
@@ -1,19 +0,0 @@ -Name: mt19937ar -URL: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html -Version: 0 -Date: 2002/1/26 -License: BSD -Security Critical: yes - -Description: -This is Chrome's locally patched copy of Takuji Nishimura and Makoto -Matsumoto's Mersenne Twister pseudorandom number generator. - -Note: Once Chromium moves to C++11, this can be removed in favor -of C++'s <random>. - -Local Modifications: -Renamed mt19937ar.c to mt19937ar.cc and modified it to encapsulate its -state in a C++ class, rather than using global state. Changed the code to -use uint32 types instead of unsigned longs. Added a header file. -Additionally, unnecessary functions (in particular, main) were removed.
diff --git a/third_party/mt19937ar/mt19937ar.cc b/third_party/mt19937ar/mt19937ar.cc deleted file mode 100644 index 8b14f30..0000000 --- a/third_party/mt19937ar/mt19937ar.cc +++ /dev/null
@@ -1,140 +0,0 @@ -/* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - 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. - - 3. The names of its contributors may not 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. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -*/ - -#include "mt19937ar.h" - -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ - -MersenneTwister::MersenneTwister() : mt(N), mti(N+1) { -} - -MersenneTwister::~MersenneTwister() { -} - -/* initializes mt[N] with a seed */ -void MersenneTwister::init_genrand(uint32_t s) -{ - mt[0]= s & 0xffffffffUL; - for (mti=1; mti<N; mti++) { - mt[mti] = - (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffUL; - /* for >32 bit machines */ - } -} - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void MersenneTwister::init_by_array(uint32_t init_key[], int key_length) -{ - int i, j, k; - init_genrand(19650218UL); - i=1; j=0; - k = (N>key_length ? N : key_length); - for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) - + init_key[j] + j; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - if (j>=key_length) j=0; - } - for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - - i; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - } - - mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ -} - -/* generates a random number on [0,0xffffffff]-interval */ -uint32_t MersenneTwister::genrand_int32(void) -{ - uint32_t y; - static uint32_t mag01[2]={0x0UL, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489UL); /* a default initial seed is used */ - - for (kk=0;kk<N-M;kk++) { - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); - mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - for (;kk<N-1;kk++) { - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); - mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -}
diff --git a/third_party/mt19937ar/mt19937ar.h b/third_party/mt19937ar/mt19937ar.h deleted file mode 100644 index e3c4f11..0000000 --- a/third_party/mt19937ar/mt19937ar.h +++ /dev/null
@@ -1,65 +0,0 @@ -/* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - 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. - - 3. The names of its contributors may not 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. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) - */ - -#ifndef THIRD_PARTY_MT19937AR_MT19937AR_H_ -#define THIRD_PARTY_MT19937AR_MT19937AR_H_ - -#include <stdint.h> - -#include <vector> - -class MersenneTwister { - public: - MersenneTwister(); - ~MersenneTwister(); - - void init_genrand(uint32_t s); - void init_by_array(uint32_t init_key[], int key_length); - uint32_t genrand_int32(void); - - private: - std::vector<uint32_t> mt; /* the array for the state vector */ - int mti; /* mti==N+1 means mt[N] is not initialized */ -}; - -#endif // THIRD_PARTY_MT19937AR_MT19937AR_H_
diff --git a/third_party/mt19937ar/readme-mt.txt b/third_party/mt19937ar/readme-mt.txt deleted file mode 100644 index c3a9c419..0000000 --- a/third_party/mt19937ar/readme-mt.txt +++ /dev/null
@@ -1,74 +0,0 @@ -This is a Mersenne Twister pseudorandom number generator -with period 2^19937-1 with improved initialization scheme, -modified on 2002/1/26 by Takuji Nishimura and Makoto Matsumoto. - -Contents of this tar ball: -readme-mt.txt this file -mt19937ar.c the C source (ar: initialize by ARray) -mt19937ar.out Test outputs of six types generators. 1000 for each - -1. Initialization - The initialization scheme for the previous versions of MT -(e.g. 1999/10/28 version or earlier) has a tiny problem, that -the most significant bits of the seed is not well reflected -to the state vector of MT. - -This version (2002/1/26) has two initialization schemes: -init_genrand(seed) and init_by_array(init_key, key_length). - -init_genrand(seed) initializes the state vector by using -one unsigned 32-bit integer "seed", which may be zero. - -init_by_array(init_key, key_length) initializes the state vector -by using an array init_key[] of unsigned 32-bit integers -of length key_kength. If key_length is smaller than 624, -then each array of 32-bit integers gives distinct initial -state vector. This is useful if you want a larger seed space -than 32-bit word. - -2. Generation -After initialization, the following type of pseudorandom numbers -are available. - -genrand_int32() generates unsigned 32-bit integers. -genrand_int31() generates unsigned 31-bit integers. -genrand_real1() generates uniform real in [0,1] (32-bit resolution). -genrand_real2() generates uniform real in [0,1) (32-bit resolution). -genrand_real3() generates uniform real in (0,1) (32-bit resolution). -genrand_res53() generates uniform real in [0,1) with 53-bit resolution. - -Note: the last five functions call the first one. -if you need more speed for these five functions, you may -suppress the function call by copying genrand_int32() and -replacing the last return(), following to these five functions. - -3. main() -main() is an example to initialize with an array of length 4, -then 1000 outputs of unsigned 32-bit integers, -then 1000 outputs of real [0,1) numbers. - -4. The outputs -The output of the mt19937ar.c is in the file mt19937ar.out. -If you revise or translate the code, check the output -by using this file. - -5. Cryptography -This generator is not cryptoraphically secure. -You need to use a one-way (or hash) function to obtain -a secure random sequence. - -6. Correspondence -See: -URL http://www.math.keio.ac.jp/matumoto/emt.html -email matumoto@math.keio.ac.jp, nisimura@sci.kj.yamagata-u.ac.jp - -7. Reference -M. Matsumoto and T. Nishimura, -"Mersenne Twister: A 623-Dimensionally Equidistributed Uniform -Pseudo-Random Number Generator", -ACM Transactions on Modeling and Computer Simulation, -Vol. 8, No. 1, January 1998, pp 3--30. - -------- -Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, -All rights reserved.
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium index 8d42ca7..3a4f72f8 100644 --- a/third_party/protobuf/README.chromium +++ b/third_party/protobuf/README.chromium
@@ -118,3 +118,7 @@ - 0019-rename-a-shadowed-variable.patch Cherry-picks upstream https://github.com/google/protobuf/commit/af3813cd7 + +- 0020-Add-support-for-libc-on-Windows.patch + + Cherry-picks upstream https://github.com/google/protobuf/commit/3ba21cd5f
diff --git a/third_party/protobuf/patches/0020-Add-support-for-libc-on-Windows.patch b/third_party/protobuf/patches/0020-Add-support-for-libc-on-Windows.patch new file mode 100644 index 0000000..a56cbc1 --- /dev/null +++ b/third_party/protobuf/patches/0020-Add-support-for-libc-on-Windows.patch
@@ -0,0 +1,42 @@ +From 3ba21cd5f724528ab8792c05bda6e06ceb557bff Mon Sep 17 00:00:00 2001 +From: Peter Collingbourne <pcc@google.com> +Date: Wed, 17 Jan 2018 16:05:47 -0800 +Subject: [PATCH] Add support for libc++ on Windows. + +This disables a couple of workarounds which are only necessary with +MSVC's standard library and cause problems with libc++. +--- + src/google/protobuf/arena.h | 2 +- + src/google/protobuf/stubs/hash.h | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h +index f3cdedac..b500b3be 100644 +--- a/src/google/protobuf/arena.h ++++ b/src/google/protobuf/arena.h +@@ -40,7 +40,7 @@ + #if LANG_CXX11 + #include <google/protobuf/stubs/type_traits.h> + #endif +-#if defined(_MSC_VER) && !_HAS_EXCEPTIONS ++#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS + // Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0. + #include <exception> + #include <typeinfo> +diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h +index 218cd948..ec1f9810 100644 +--- a/src/google/protobuf/stubs/hash.h ++++ b/src/google/protobuf/stubs/hash.h +@@ -235,7 +235,8 @@ class hash_set : public std::set<Key, HashFcn> { + HashFcn hash_function() const { return HashFcn(); } + }; + +-#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) ++#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) && \ ++ !(defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) + + template <typename Key> + struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> { +-- +2.16.2.395.g2e18187dfd-goog +
diff --git a/third_party/protobuf/src/google/protobuf/arena.h b/third_party/protobuf/src/google/protobuf/arena.h index 0ffc600..954422fe 100644 --- a/third_party/protobuf/src/google/protobuf/arena.h +++ b/third_party/protobuf/src/google/protobuf/arena.h
@@ -40,7 +40,7 @@ #if __cplusplus >= 201103L #include <google/protobuf/stubs/type_traits.h> #endif -#if defined(_MSC_VER) && !_HAS_EXCEPTIONS +#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS // Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0. #include <exception> #include <typeinfo>
diff --git a/third_party/protobuf/src/google/protobuf/stubs/hash.h b/third_party/protobuf/src/google/protobuf/stubs/hash.h index 612b586..25f8f4c5 100644 --- a/third_party/protobuf/src/google/protobuf/stubs/hash.h +++ b/third_party/protobuf/src/google/protobuf/stubs/hash.h
@@ -235,7 +235,8 @@ HashFcn hash_function() const { return HashFcn(); } }; -#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) +#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) && \ + !(defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) template <typename Key> struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
diff --git a/tools/ipc_fuzzer/fuzzer/DEPS b/tools/ipc_fuzzer/fuzzer/DEPS index 64488680..48e88750 100644 --- a/tools/ipc_fuzzer/fuzzer/DEPS +++ b/tools/ipc_fuzzer/fuzzer/DEPS
@@ -1,3 +1,2 @@ include_rules = [ - "+third_party/mt19937ar", ]
diff --git a/tools/ipc_fuzzer/fuzzer/rand_util.cc b/tools/ipc_fuzzer/fuzzer/rand_util.cc index 5483c33..e0a16e8e 100644 --- a/tools/ipc_fuzzer/fuzzer/rand_util.cc +++ b/tools/ipc_fuzzer/fuzzer/rand_util.cc
@@ -7,12 +7,11 @@ namespace ipc_fuzzer { -MersenneTwister* g_mersenne_twister = NULL; +std::mt19937* g_mersenne_twister = nullptr; void InitRand() { - // TODO(aedla): convert to C++11 std::mt19937 in the future - g_mersenne_twister = new MersenneTwister(); - g_mersenne_twister->init_genrand(static_cast<uint32_t>(base::RandUint64())); + g_mersenne_twister = + new std::mt19937(static_cast<uint32_t>(base::RandUint64())); } } // namespace ipc_fuzzer
diff --git a/tools/ipc_fuzzer/fuzzer/rand_util.h b/tools/ipc_fuzzer/fuzzer/rand_util.h index d1afa086..af433c0d 100644 --- a/tools/ipc_fuzzer/fuzzer/rand_util.h +++ b/tools/ipc_fuzzer/fuzzer/rand_util.h
@@ -7,17 +7,16 @@ #include <stddef.h> #include <stdint.h> - -#include "third_party/mt19937ar/mt19937ar.h" +#include <random> namespace ipc_fuzzer { -extern MersenneTwister* g_mersenne_twister; +extern std::mt19937* g_mersenne_twister; void InitRand(); inline uint32_t RandU32() { - return g_mersenne_twister->genrand_int32(); + return (*g_mersenne_twister)(); } inline uint64_t RandU64() {
diff --git a/tools/ipc_fuzzer/message_lib/BUILD.gn b/tools/ipc_fuzzer/message_lib/BUILD.gn index 3852da3f..b68c7c7 100644 --- a/tools/ipc_fuzzer/message_lib/BUILD.gn +++ b/tools/ipc_fuzzer/message_lib/BUILD.gn
@@ -28,7 +28,6 @@ "//skia", "//third_party/WebKit/public:blink", "//third_party/WebKit/public:blink_headers", - "//third_party/mt19937ar", "//third_party/webrtc_overrides", "//ui/accessibility:ax_enums_mojo", ]
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index ab36f56..51e12e0 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -557,7 +557,7 @@ 'android_mojo': 'android_release_trybot_arm64', 'android_n5x_swarming_dbg': 'android_debug_trybot_arm64', - 'android_n5x_swarming_rel': 'android_release_trybot_arm64', + 'android_n5x_swarming_rel': 'android_release_trybot_arm64_no_symbols', 'android_optional_gpu_tests_rel': 'gpu_tests_android_release_trybot_arm64', 'android_unswarmed_n5_rel': 'android_release_trybot', 'android_unswarmed_n5x_rel': 'android_release_trybot_arm64', @@ -978,6 +978,10 @@ 'android', 'release_trybot', 'arm64', 'strip_debug_info', ], + 'android_release_trybot_arm64_no_symbols': [ + 'android', 'release_trybot', 'arm64', 'no_symbols', + ], + 'android_shared_release_bot_x64': [ 'android_without_codecs', 'shared_release_bot', 'x64', 'dcheck_always_on', ],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index c437666b..1b1bed5 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -25788,6 +25788,7 @@ <int value="-1581724231" label="ModalPermissionPrompts:enabled"/> <int value="-1580376019" label="ShowAllDialogsWithViewsToolkit:enabled"/> <int value="-1578295753" label="UserMediaScreenCapturing:disabled"/> + <int value="-1575772949" label="DesktopPWAsLinkCapturing:disabled"/> <int value="-1575554415" label="AndroidPaymentAppsFilter:enabled"/> <int value="-1575430234" label="DontPrefetchLibraries:disabled"/> <int value="-1575375861" label="enable-captive-portal-random-url"/> @@ -26730,6 +26731,7 @@ <int value="772272625" label="simplify-https-indicator"/> <int value="772348426" label="AffiliationBasedMatching:enabled"/> <int value="773919225" label="disable-office-editing-component-extension"/> + <int value="777667507" label="DesktopPWAsLinkCapturing:enabled"/> <int value="779086132" label="enable-data-reduction-proxy-alt"/> <int value="782167080" label="enable-new-qp-input-view"/> <int value="783270752" label="AndroidHistoryManager:enabled"/> @@ -44068,10 +44070,12 @@ <int value="18764319" label="webstore_installer"/> <int value="19185953" label="offline_prefetch"/> <int value="20053290" label="cryptauth_find_eligible_for_promotion"/> + <int value="20153177" label="quic_chromium_packet_writer"/> <int value="21145003" label="extension_crx_fetcher"/> <int value="21785164" label="intranet_redirect_detector"/> <int value="22096011" label="test_partial"/> <int value="22265491" label="user_info_fetcher"/> + <int value="22573197" label="cast_udp_socket"/> <int value="22774132" label="devtools_free_data_source"/> <int value="23472048" label="network_location_provider"/> <int value="24058523" label="CRD_relay_session_request"/> @@ -44101,6 +44105,7 @@ <int value="36859107" label="logo_tracker"/> <int value="37249086" label="android_device_manager_socket"/> <int value="37531401" label="proxy_script_fetcher"/> + <int value="38670228" label="download_internals_webui_source"/> <int value="39356976" label="android_web_socket"/> <int value="39877119" label="gaia_auth_exchange_device_id"/> <int value="40534770" label="obsolete_favicon_component"/> @@ -44170,6 +44175,7 @@ <int value="78917933" label="one_google_bar_service"/> <int value="79227717" label="dns_transaction"/> <int value="79442849" label="sigined_exchange_cert_fetcher"/> + <int value="79895226" label="dns_over_https"/> <int value="79957943" label="safe_browsing_chunk_backup_request"/> <int value="80832574" label="history_notice_utils_popup"/> <int value="81157007" label="resource_dispatcher_host"/> @@ -44182,6 +44188,7 @@ <int value="84575287" label="background_performance_tracer"/> <int value="84889397" label="cryptauth_enrollment_flow_setup"/> <int value="87558948" label="cast_message_handler"/> + <int value="87635401" label="quic_chromium_incoming_session"/> <int value="87775794" label="adb_client_socket"/> <int value="88754904" label="captive_portal_service"/> <int value="88863520" label="autofill_query"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index fff6d32..b834d13 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -10858,6 +10858,20 @@ <histogram name="Compositing.Display.Draw.Occlusion.Drawing.Area.Saved" units="px"> + <obsolete> + Deprecated 02/2018, replaced by similar metric + Compositing.Display.Draw.Occlusion.Drawing.Area.Saved2. + </obsolete> + <owner>yiyix@chromium.org</owner> + <summary> + It records the total drawing area skipped to show on screen as a result of + applying draw occlusion. This is logged once per frame, when the frame is + drawn. + </summary> +</histogram> + +<histogram name="Compositing.Display.Draw.Occlusion.Drawing.Area.Saved2" + units="px"> <owner>yiyix@chromium.org</owner> <summary> It records the total drawing area skipped to show on screen as a result of @@ -10884,6 +10898,15 @@ </summary> </histogram> +<histogram name="Compositing.Display.Draw.Quads.With.Complex.Transform.Area" + units="px"> + <owner>yiyix@chromium.org</owner> + <summary> + This is logged once per frame, when the frame is drawn. Captures area of all + draw quads that need to go through no scale and no translation transforms. + </summary> +</histogram> + <histogram name="Compositing.DisplayListRecordingSource.UpdateInvalidatedAreaPerMs" units="pixels/ms">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index dbd7301..7222c259 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -2636,6 +2636,11 @@ |chromeos::power::ml::UserActivityEvent::Event::Type|. </summary> </metric> + <metric name="KeyEventsInLastHour"> + <summary> + Number of key events in the past hour. + </summary> + </metric> <metric name="LastActivityDay"> <summary> An enum representing the last activity day of the week, defined in @@ -2652,6 +2657,11 @@ Last user activity time as hours since midnight in the local time zone. </summary> </metric> + <metric name="MouseEventsInLastHour"> + <summary> + Number of mouse events in the past hour. + </summary> + </metric> <metric name="OnBattery"> <summary> Boolean value to represent whether the device is currently on battery @@ -2700,6 +2710,11 @@ Time from the end of the last video playing in seconds. </summary> </metric> + <metric name="TouchEventsInLastHour"> + <summary> + Number of touch events in the past hour. + </summary> + </metric> </event> <event name="UserActivityId">
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index fa253581..f9468606 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -198,6 +198,10 @@ # Benchmark: smoothness.tough_webgl_ad_cases crbug.com/574485 [ Android_Svelte ] smoothness.tough_webgl_ad_cases/* [ Skip ] +# Benchmark: speedometer2-future +crbug.com/792495 [ Linux ] speedometer2-future/Speedometer2 [ Skip ] +crbug.com/784025 [ Win ] speedometer2-future/Speedometer2 [ Skip ] + # Benchmark: system_health.common_desktop crbug.com/728576 [ Mac ] system_health.common_desktop/browse:news:cnn [ Skip ] crbug.com/64939 [ All ] system_health.common_desktop/play:media:pandora [ Skip ]
diff --git a/tools/perf/measurements/skpicture_printer_unittest.py b/tools/perf/measurements/skpicture_printer_unittest.py index 1c347a5..206e3f1 100644 --- a/tools/perf/measurements/skpicture_printer_unittest.py +++ b/tools/perf/measurements/skpicture_printer_unittest.py
@@ -21,17 +21,13 @@ def tearDown(self): shutil.rmtree(self._skp_outdir) - @decorators.Disabled('android') + # Picture printing is not supported on all platforms. + @decorators.Disabled('android', 'chromeos') def testSkpicturePrinter(self): ps = self.CreateStorySetFromFileInUnittestDataDir('blank.html') measurement = skpicture_printer.SkpicturePrinter(self._skp_outdir) results = self.RunMeasurement(measurement, ps, options=self._options) - # Picture printing is not supported on all platforms. - if results.failures: - assert 'not supported' in results.failures[0].exc_info[1].message - return - saved_picture_count = results.FindAllPageSpecificValuesNamed( 'saved_picture_count') self.assertEquals(len(saved_picture_count), 1)
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc index 0ceda53..28e78a2 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc
@@ -55,6 +55,8 @@ get updated and if it does, 'tools/traffic_annotation/ scripts/annotations_xml_downstream_updater.py will be called to update downstream files. + --no-missing-error Optional argument, resulting in just issuing a warning for + functions that miss annotation and not an error. --summary-file Optional path to the output file with all annotations. --annotations-file Optional path to a TSV output file with all annotations. --limit Limit for the maximum number of returned errors. @@ -334,6 +336,7 @@ bool filter_files = !command_line.HasSwitch("no-filtering"); bool all_files = command_line.HasSwitch("all-files"); bool test_only = command_line.HasSwitch("test-only"); + bool no_missing_error = command_line.HasSwitch("no-missing-error"); base::FilePath summary_file = command_line.GetSwitchValuePath("summary-file"); base::FilePath annotations_file = command_line.GetSwitchValuePath("annotations-file"); @@ -446,7 +449,23 @@ } } - const std::vector<AuditorResult>& errors = auditor.errors(); + const std::vector<AuditorResult>& raw_errors = auditor.errors(); + + std::vector<AuditorResult> errors; + std::vector<AuditorResult> warnings; + std::set<AuditorResult::Type> warning_types; + + if (no_missing_error) { + warning_types.insert(AuditorResult::Type::ERROR_MISSING_ANNOTATION); + warning_types.insert(AuditorResult::Type::ERROR_NO_ANNOTATION); + } + + for (const AuditorResult& result : raw_errors) { + if (base::ContainsKey(warning_types, result.type())) + warnings.push_back(result); + else + errors.push_back(result); + } // Update annotations.xml if everything else is OK and the auditor is not // run in test-only mode. @@ -458,17 +477,26 @@ } } - // Dump Errors to stdout. + // Dump Warnings and Errors to stdout. + int remaining_outputs = + outputs_limit ? outputs_limit + : static_cast<int>(errors.size() + warnings.size()); if (errors.size()) { printf("[Errors]\n"); - for (int i = 0; i < static_cast<int>(errors.size()); i++) { + for (int i = 0; i < static_cast<int>(errors.size()) && remaining_outputs; + i++, remaining_outputs--) { printf(" (%i)\t%s\n", i + 1, errors[i].ToText().c_str()); - if (i + 1 == outputs_limit) - break; } - } else { - printf("Traffic annotations are all OK.\n"); } + if (warnings.size() && remaining_outputs) { + printf("[Warnings]\n"); + for (int i = 0; i < static_cast<int>(warnings.size()) && remaining_outputs; + i++, remaining_outputs--) { + printf(" (%i)\t%s\n", i + 1, warnings[i].ToText().c_str()); + } + } + if (warnings.empty() && errors.empty()) + printf("Traffic annotations are all OK.\n"); return static_cast<int>(errors.size()); } \ No newline at end of file
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 0a5b2a5..6b05628 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -174,6 +174,8 @@ <item id="profile_avatar" hash_code="51164680" type="0" content_hash_code="113550845" os_list="linux,windows" file_path="chrome/browser/profiles/profile_avatar_downloader.cc"/> <item id="profile_resetter_upload" hash_code="105330607" type="0" content_hash_code="129329171" os_list="linux,windows" file_path="chrome/browser/profile_resetter/reset_report_uploader.cc"/> <item id="proxy_script_fetcher" hash_code="37531401" type="0" content_hash_code="31866133" os_list="linux,windows" file_path="net/proxy_resolution/pac_file_fetcher_impl.cc"/> + <item id="quic_chromium_incoming_session" hash_code="87635401" type="0" content_hash_code="78573093" os_list="linux,windows" file_path="net/quic/chromium/quic_chromium_client_session.cc"/> + <item id="quic_chromium_packet_writer" hash_code="20153177" type="0" content_hash_code="29657765" os_list="linux,windows" file_path="net/quic/chromium/quic_chromium_packet_writer.cc"/> <item id="ranker_url_fetcher" hash_code="95682324" type="0" content_hash_code="45958626" os_list="linux,windows" file_path="components/assist_ranker/ranker_url_fetcher.cc"/> <item id="rappor_report" hash_code="44606780" type="0" content_hash_code="111287826" os_list="linux,windows" file_path="components/rappor/log_uploader.cc"/> <item id="refresh_token_annotation_request" hash_code="7433837" type="1" second_id="29188932" deprecated="2018-01-17" content_hash_code="137103383" file_path=""/>
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc index ec292c7..52747b1 100644 --- a/ui/accessibility/ax_event_generator.cc +++ b/ui/accessibility/ax_event_generator.cc
@@ -397,8 +397,8 @@ AXNode* target_node) { int32_t target_id = target_node->id(); std::set<AXNode*> source_nodes; - auto callback = [&](const auto entry) { - const auto target_to_sources = entry.second; + auto callback = [&](const auto& entry) { + const auto& target_to_sources = entry.second; auto sources_it = target_to_sources.find(target_id); if (sources_it == target_to_sources.end()) return;
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc index 618b51e3..c171556d 100644 --- a/ui/aura/client/aura_constants.cc +++ b/ui/aura/client/aura_constants.cc
@@ -73,6 +73,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(int, kTopViewInset, 0); DEFINE_UI_CLASS_PROPERTY_KEY(SkColor, kTopViewColor, SK_ColorTRANSPARENT); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kWindowIconKey, nullptr); +DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowCornerRadiusKey, -1); DEFINE_UI_CLASS_PROPERTY_KEY(ui::mojom::WindowType, kWindowTypeKey, ui::mojom::WindowType::UNKNOWN);
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h index 3730ab71..f0f8b6c 100644 --- a/ui/aura/client/aura_constants.h +++ b/ui/aura/client/aura_constants.h
@@ -152,6 +152,10 @@ // Indicates the type of embedding within the given window. AURA_EXPORT extern const WindowProperty<WindowEmbedType>* const kEmbedType; +// The corner radius of a window in DIPs. Currently only used for shadows. +// Default is -1, meaning "unspecified". 0 Ensures corners are square. +AURA_EXPORT extern const WindowProperty<int>* const kWindowCornerRadiusKey; + AURA_EXPORT extern const WindowProperty<ui::mojom::WindowType>* const kWindowTypeKey;
diff --git a/ui/aura/mus/property_converter.cc b/ui/aura/mus/property_converter.cc index 8839c507..7a0a67e 100644 --- a/ui/aura/mus/property_converter.cc +++ b/ui/aura/mus/property_converter.cc
@@ -49,6 +49,10 @@ value == int64_t(ui::mojom::ShowState::FULLSCREEN); } +bool ValidateWindowCornerRadius(int64_t value) { + return value >= -1; +} + } // namespace PropertyConverter::PrimitiveProperty::PrimitiveProperty() {} @@ -96,6 +100,10 @@ ui::mojom::WindowManager::kName_Property); RegisterString16Property(client::kTitleKey, ui::mojom::WindowManager::kWindowTitle_Property); + RegisterPrimitiveProperty( + client::kWindowCornerRadiusKey, + ui::mojom::WindowManager::kWindowCornerRadius_Property, + base::BindRepeating(&ValidateWindowCornerRadius)); } PropertyConverter::~PropertyConverter() {}
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc index 61b37ba..1ed6c0c 100644 --- a/ui/aura/mus/window_tree_client_unittest.cc +++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -537,6 +537,9 @@ data->properties[ui::mojom::WindowManager::kWindowType_InitProperty] = mojo::ConvertTo<std::vector<uint8_t>>( static_cast<int32_t>(ui::mojom::WindowType::BUBBLE)); + constexpr int kWindowCornerRadiusValue = 6; + data->properties[ui::mojom::WindowManager::kWindowCornerRadius_Property] = + ConvertToPropertyTransportValue(kWindowCornerRadiusValue); data->parent_id = server_id(root_window()); data->window_id = child_window_id; data->bounds = gfx::Rect(1, 2, 3, 4); @@ -551,6 +554,8 @@ Window* child = root_window()->children()[0]; EXPECT_FALSE(child->TargetVisibility()); EXPECT_EQ(server_test_property1_value, child->GetProperty(kTestPropertyKey1)); + EXPECT_EQ(kWindowCornerRadiusValue, + child->GetProperty(client::kWindowCornerRadiusKey)); EXPECT_EQ(child->type(), client::WINDOW_TYPE_POPUP); EXPECT_EQ(ui::mojom::WindowType::BUBBLE, child->GetProperty(client::kWindowTypeKey));
diff --git a/ui/base/cocoa/text_services_context_menu.cc b/ui/base/cocoa/text_services_context_menu.cc index d675d0e6..f7cb1dc 100644 --- a/ui/base/cocoa/text_services_context_menu.cc +++ b/ui/base/cocoa/text_services_context_menu.cc
@@ -21,18 +21,46 @@ // channel is currently speaking. SpeechChannel g_speech_channel; +// Returns the TextDirection associated associated with the given BiDi +// |command_id|. +base::i18n::TextDirection GetTextDirectionFromCommandId(int command_id) { + switch (command_id) { + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: + return base::i18n::UNKNOWN_DIRECTION; + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: + return base::i18n::LEFT_TO_RIGHT; + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + return base::i18n::RIGHT_TO_LEFT; + default: + NOTREACHED(); + return base::i18n::UNKNOWN_DIRECTION; + } +} + } // namespace namespace ui { TextServicesContextMenu::TextServicesContextMenu(Delegate* delegate) - : speech_submenu_model_(this), delegate_(delegate) { + : speech_submenu_model_(this), + bidi_submenu_model_(this), + delegate_(delegate) { DCHECK(delegate); speech_submenu_model_.AddItemWithStringId(IDS_SPEECH_START_SPEAKING_MAC, IDS_SPEECH_START_SPEAKING_MAC); speech_submenu_model_.AddItemWithStringId(IDS_SPEECH_STOP_SPEAKING_MAC, IDS_SPEECH_STOP_SPEAKING_MAC); + + bidi_submenu_model_.AddCheckItemWithStringId( + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT, + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT); + bidi_submenu_model_.AddCheckItemWithStringId( + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR, + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR); + bidi_submenu_model_.AddCheckItemWithStringId( + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL, + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL); } void TextServicesContextMenu::SpeakText(const base::string16& text) { @@ -64,8 +92,19 @@ &speech_submenu_model_); } +void TextServicesContextMenu::AppendEditableItems(SimpleMenuModel* model) { + model->AddSubMenuWithStringId(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU, + IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU, + &bidi_submenu_model_); +} + bool TextServicesContextMenu::IsCommandIdChecked(int command_id) const { switch (command_id) { + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + return delegate_->IsTextDirectionChecked( + GetTextDirectionFromCommandId(command_id)); case IDS_SPEECH_START_SPEAKING_MAC: case IDS_SPEECH_STOP_SPEAKING_MAC: return false; @@ -77,6 +116,11 @@ bool TextServicesContextMenu::IsCommandIdEnabled(int command_id) const { switch (command_id) { + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + return delegate_->IsTextDirectionEnabled( + GetTextDirectionFromCommandId(command_id)); case IDS_SPEECH_START_SPEAKING_MAC: return true; case IDS_SPEECH_STOP_SPEAKING_MAC: @@ -89,6 +133,11 @@ void TextServicesContextMenu::ExecuteCommand(int command_id, int event_flags) { switch (command_id) { + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: + case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + delegate_->UpdateTextDirection(GetTextDirectionFromCommandId(command_id)); + break; case IDS_SPEECH_START_SPEAKING_MAC: SpeakText(delegate_->GetSelectedText()); break;
diff --git a/ui/base/cocoa/text_services_context_menu.h b/ui/base/cocoa/text_services_context_menu.h index dbc47136..2c163d7 100644 --- a/ui/base/cocoa/text_services_context_menu.h +++ b/ui/base/cocoa/text_services_context_menu.h
@@ -5,6 +5,7 @@ #ifndef UI_BASE_COCOA_TEXT_SERVICES_CONTEXT_MENU_H_ #define UI_BASE_COCOA_TEXT_SERVICES_CONTEXT_MENU_H_ +#include "base/i18n/rtl.h" #include "base/macros.h" #include "base/strings/string16.h" #include "ui/base/models/simple_menu_model.h" @@ -14,7 +15,7 @@ // This class is used to append and handle the Speech and BiDi submenu for the // context menu. -// TODO (spqchan): Replace the Speech logic in RenderViewContextMenu +// TODO (spqchan): Replace the Speech and BiDi logic in RenderViewContextMenu // with TextServicesContextMenu. class UI_BASE_EXPORT TextServicesContextMenu : public SimpleMenuModel::Delegate { @@ -23,6 +24,17 @@ public: // Returns the selected text. virtual base::string16 GetSelectedText() const = 0; + + // Returns true if |direction| should be enabled in the BiDi submenu. + virtual bool IsTextDirectionEnabled( + base::i18n::TextDirection direction) const = 0; + + // Returns true if |direction| should be checked in the BiDi submenu. + virtual bool IsTextDirectionChecked( + base::i18n::TextDirection direction) const = 0; + + // Updates the text direction to |direction|. + virtual void UpdateTextDirection(base::i18n::TextDirection direction) = 0; }; explicit TextServicesContextMenu(Delegate* delegate); @@ -36,6 +48,10 @@ // which |this| serves as the delegate for. void AppendToContextMenu(SimpleMenuModel* model); + // Appends items to the context menu applicable to editable content. A + // submenu is added for bidirection, which |this| serves as a delegate for. + void AppendEditableItems(SimpleMenuModel* model); + // SimpleMenuModel::Delegate: bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; @@ -45,6 +61,9 @@ // Model for the "Speech" submenu. ui::SimpleMenuModel speech_submenu_model_; + // Model for the BiDi input submenu. + ui::SimpleMenuModel bidi_submenu_model_; + Delegate* delegate_; // Weak. DISALLOW_COPY_AND_ASSIGN(TextServicesContextMenu);
diff --git a/ui/events/base_event_utils.cc b/ui/events/base_event_utils.cc index 6eee6f1..20bbed9d 100644 --- a/ui/events/base_event_utils.cc +++ b/ui/events/base_event_utils.cc
@@ -47,7 +47,7 @@ (EF_ALTGR_DOWN & flags) == 0; } -base::LazyInstance<std::unique_ptr<base::TickClock>>::Leaky g_tick_clock = +base::LazyInstance<base::TickClock*>::Leaky g_tick_clock = LAZY_INSTANCE_INITIALIZER; base::TimeTicks EventTimeForNow() { @@ -55,8 +55,8 @@ : base::TimeTicks::Now(); } -void SetEventTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock) { - g_tick_clock.Get() = std::move(tick_clock); +void SetEventTickClockForTesting(base::TickClock* tick_clock) { + g_tick_clock.Get() = tick_clock; } double EventTimeStampToSeconds(base::TimeTicks time_stamp) {
diff --git a/ui/events/base_event_utils.h b/ui/events/base_event_utils.h index 4e177803..d030fd15 100644 --- a/ui/events/base_event_utils.h +++ b/ui/events/base_event_utils.h
@@ -27,8 +27,10 @@ // Create a timestamp based on the current time. EVENTS_BASE_EXPORT base::TimeTicks EventTimeForNow(); +// Overrides the clock used by EventTimeForNow for testing. +// This doesn't take the ownership of the clock. EVENTS_BASE_EXPORT void SetEventTickClockForTesting( - std::unique_ptr<base::TickClock> tick_clock); + base::TickClock* tick_clock); // Converts an event timestamp ticks to seconds (floating point representation). // WARNING: This should only be used when interfacing with platform code that
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 634296b..e9dd5025 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -161,7 +161,7 @@ current_overscroll_params_(nullptr), has_ongoing_compositor_scroll_fling_pinch_(false), is_first_gesture_scroll_update_(false), - tick_clock_(std::make_unique<base::DefaultTickClock>()) { + tick_clock_(base::DefaultTickClock::GetInstance()) { DCHECK(client); input_handler_->BindToClient(this, touchpad_and_wheel_scroll_latching_enabled_); @@ -1330,9 +1330,8 @@ scroll_result)); } -void InputHandlerProxy::SetTickClockForTesting( - std::unique_ptr<base::TickClock> tick_clock) { - tick_clock_ = std::move(tick_clock); +void InputHandlerProxy::SetTickClockForTesting(base::TickClock* tick_clock) { + tick_clock_ = tick_clock; } void InputHandlerProxy::UpdateCurrentFlingState(
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h index bb67ec4..feeea9d 100644 --- a/ui/events/blink/input_handler_proxy.h +++ b/ui/events/blink/input_handler_proxy.h
@@ -176,7 +176,10 @@ const blink::WebGestureEvent& gesture_event, const cc::InputHandlerScrollResult& scroll_result); - void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock); + // Overrides the internal clock for testing. + // This doesn't take the ownership of the clock. |tick_clock| must outlive the + // InputHandlerProxy instance. + void SetTickClockForTesting(base::TickClock* tick_clock); // |is_touching_scrolling_layer| indicates if one of the points that has // been touched hits a currently scrolling layer. @@ -257,7 +260,7 @@ bool has_ongoing_compositor_scroll_fling_pinch_; bool is_first_gesture_scroll_update_; - std::unique_ptr<base::TickClock> tick_clock_; + base::TickClock* tick_clock_; std::unique_ptr<FlingBooster> fling_booster_;
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc index 4defce8a..2f1830b4 100644 --- a/ui/events/blink/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -563,9 +563,8 @@ return input_handler_proxy_->compositor_event_queue_->queue_; } - void SetInputHandlerProxyTickClockForTesting( - std::unique_ptr<base::TickClock> tick_clock) { - input_handler_proxy_->SetTickClockForTesting(std::move(tick_clock)); + void SetInputHandlerProxyTickClockForTesting(base::TickClock* tick_clock) { + input_handler_proxy_->SetTickClockForTesting(tick_clock); } protected: @@ -3024,11 +3023,9 @@ TEST_P(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) { base::HistogramTester histogram_tester; - std::unique_ptr<base::SimpleTestTickClock> tick_clock = - std::make_unique<base::SimpleTestTickClock>(); - base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get(); - tick_clock_ptr->SetNowTicks(base::TimeTicks::Now()); - SetInputHandlerProxyTickClockForTesting(std::move(tick_clock)); + base::SimpleTestTickClock tick_clock; + tick_clock.SetNowTicks(base::TimeTicks::Now()); + SetInputHandlerProxyTickClockForTesting(&tick_clock); // Handle scroll on compositor. cc::InputHandlerScrollResult scroll_result_did_scroll_; @@ -3044,17 +3041,17 @@ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true)); HandleGestureEvent(WebInputEvent::kGestureScrollBegin); - tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(10)); + tick_clock.Advance(base::TimeDelta::FromMicroseconds(10)); HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20); - tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(40)); + tick_clock.Advance(base::TimeDelta::FromMicroseconds(40)); HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40); - tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(20)); + tick_clock.Advance(base::TimeDelta::FromMicroseconds(20)); HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10); - tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(10)); + tick_clock.Advance(base::TimeDelta::FromMicroseconds(10)); HandleGestureEvent(WebInputEvent::kGestureScrollEnd); // Dispatch all queued events. - tick_clock_ptr->Advance(base::TimeDelta::FromMicroseconds(70)); + tick_clock.Advance(base::TimeDelta::FromMicroseconds(70)); input_handler_proxy_->DeliverInputForBeginFrame(); EXPECT_EQ(0ul, event_queue().size()); EXPECT_EQ(5ul, event_disposition_recorder_.size());
diff --git a/ui/events/test/event_generator.cc b/ui/events/test/event_generator.cc index 941433d..5f97117 100644 --- a/ui/events/test/event_generator.cc +++ b/ui/events/test/event_generator.cc
@@ -36,10 +36,6 @@ namespace ui { namespace test { -namespace { - -void DummyCallback(EventType, const gfx::Vector2dF&) { -} class TestTickClock : public base::TickClock { public: @@ -57,6 +53,10 @@ DISALLOW_COPY_AND_ASSIGN(TestTickClock); }; +namespace { + +void DummyCallback(EventType, const gfx::Vector2dF&) {} + class TestTouchEvent : public ui::TouchEvent { public: TestTouchEvent(ui::EventType type, @@ -306,14 +306,18 @@ } void EventGenerator::GestureTapAt(const gfx::Point& location) { + UpdateCurrentDispatcher(location); + gfx::Point converted_location = location; + delegate()->ConvertPointToTarget(current_target_, &converted_location); + const int kTouchId = 2; ui::TouchEvent press( - ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), + ui::ET_TOUCH_PRESSED, converted_location, ui::EventTimeForNow(), ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, kTouchId)); Dispatch(&press); ui::TouchEvent release( - ui::ET_TOUCH_RELEASED, location, + ui::ET_TOUCH_RELEASED, converted_location, press.time_stamp() + base::TimeDelta::FromMilliseconds(50), ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, kTouchId)); Dispatch(&release); @@ -625,7 +629,8 @@ void EventGenerator::Init(gfx::NativeWindow root_window, gfx::NativeWindow window_context) { - ui::SetEventTickClockForTesting(std::make_unique<TestTickClock>()); + tick_clock_ = std::make_unique<TestTickClock>(); + ui::SetEventTickClockForTesting(tick_clock_.get()); delegate()->SetContext(this, root_window, window_context); if (window_context) current_location_ = delegate()->CenterOfWindow(window_context);
diff --git a/ui/events/test/event_generator.h b/ui/events/test/event_generator.h index 2b224647..79ec888 100644 --- a/ui/events/test/event_generator.h +++ b/ui/events/test/event_generator.h
@@ -18,10 +18,6 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/native_widget_types.h" -namespace base { -class TickClock; -} - namespace gfx { class PointF; } @@ -35,6 +31,7 @@ typedef base::Callback<void(EventType, const gfx::Vector2dF&)> ScrollStepCallback; +class TestTickClock; class EventGenerator; // A delegate interface for EventGenerator to abstract platform-specific event @@ -488,7 +485,7 @@ Target target_ = Target::WIDGET; - std::unique_ptr<base::TickClock> tick_clock_; + std::unique_ptr<TestTickClock> tick_clock_; DISALLOW_COPY_AND_ASSIGN(EventGenerator); };
diff --git a/ui/events/test/scoped_event_test_tick_clock.h b/ui/events/test/scoped_event_test_tick_clock.h index 966c4ab..84516d83 100644 --- a/ui/events/test/scoped_event_test_tick_clock.h +++ b/ui/events/test/scoped_event_test_tick_clock.h
@@ -23,23 +23,18 @@ // } class ScopedEventTestTickClock { public: - ScopedEventTestTickClock() { - test_clock_ = new base::SimpleTestTickClock(); - // Give up ownership of the test clock. - ui::SetEventTickClockForTesting(base::WrapUnique(test_clock_)); - } - + ScopedEventTestTickClock() { ui::SetEventTickClockForTesting(&test_clock_); } ~ScopedEventTestTickClock() { ui::SetEventTickClockForTesting(nullptr); } void SetNowSeconds(int64_t seconds) { - test_clock_->SetNowTicks(base::TimeTicks() + - base::TimeDelta::FromSeconds(seconds)); + test_clock_.SetNowTicks(base::TimeTicks() + + base::TimeDelta::FromSeconds(seconds)); } - void SetNowTicks(base::TimeTicks ticks) { test_clock_->SetNowTicks(ticks); } + void SetNowTicks(base::TimeTicks ticks) { test_clock_.SetNowTicks(ticks); } private: - base::SimpleTestTickClock* test_clock_; + base::SimpleTestTickClock test_clock_; DISALLOW_COPY_AND_ASSIGN(ScopedEventTestTickClock); }; @@ -47,4 +42,4 @@ } // namespace test } // namespace ui -#endif // UI_EVENTS_TEST_SCOPED_EVENT_TEST_TICK_CLOCK_H_ \ No newline at end of file +#endif // UI_EVENTS_TEST_SCOPED_EVENT_TEST_TICK_CLOCK_H_
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc index fa0291e4..0022b7f 100644 --- a/ui/events/x/events_x_unittest.cc +++ b/ui/events/x/events_x_unittest.cc
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/test/simple_test_tick_clock.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/devices/x11/device_data_manager_x11.h" @@ -548,30 +549,22 @@ return base::TimeTicks() + base::TimeDelta::FromMilliseconds(millis); } -class MockTickClock : public base::TickClock { - public: - explicit MockTickClock(int64_t milliseconds) - : ticks_(TimeTicksFromMillis(milliseconds)) {} - base::TimeTicks NowTicks() override { return ticks_; } - - private: - base::TimeTicks ticks_; -}; - } // namespace TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) { XEvent event; InitButtonEvent(&event, true, gfx::Point(5, 10), 1, 0); - ResetTimestampRolloverCountersForTesting( - std::make_unique<MockTickClock>(0x100000001)); + base::SimpleTestTickClock clock; + clock.SetNowTicks(TimeTicksFromMillis(0x100000001)); + SetEventTickClockForTesting(&clock); + ResetTimestampRolloverCountersForTesting(); event.xbutton.time = 0xFFFFFFFF; EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event)); - ResetTimestampRolloverCountersForTesting( - std::make_unique<MockTickClock>(0x100000007)); + clock.SetNowTicks(TimeTicksFromMillis(0x100000007)); + ResetTimestampRolloverCountersForTesting(); event.xbutton.time = 3; EXPECT_EQ(TimeTicksFromMillis(0x100000000 + 3), @@ -582,15 +575,18 @@ XEvent event; InitButtonEvent(&event, true, gfx::Point(5, 10), 1, 0); - ResetTimestampRolloverCountersForTesting(std::make_unique<MockTickClock>(10)); + base::SimpleTestTickClock clock; + clock.SetNowTicks(TimeTicksFromMillis(10)); + SetEventTickClockForTesting(&clock); + ResetTimestampRolloverCountersForTesting(); event.xbutton.time = 6; EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromNative(&event)); event.xbutton.time = 7; EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromNative(&event)); - ResetTimestampRolloverCountersForTesting( - std::make_unique<MockTickClock>(0x100000005)); + clock.SetNowTicks(TimeTicksFromMillis(0x100000005)); + ResetTimestampRolloverCountersForTesting(); event.xbutton.time = 0xFFFFFFFF; EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
diff --git a/ui/events/x/events_x_utils.cc b/ui/events/x/events_x_utils.cc index c530e97..6ad9ba9 100644 --- a/ui/events/x/events_x_utils.cc +++ b/ui/events/x/events_x_utils.cc
@@ -819,11 +819,9 @@ return XModifierStateWatcher::GetInstance()->state() & Mod1Mask; } -void ResetTimestampRolloverCountersForTesting( - std::unique_ptr<base::TickClock> tick_clock) { +void ResetTimestampRolloverCountersForTesting() { g_last_seen_timestamp_ms = 0; g_rollover_ms = 0; - SetEventTickClockForTesting(std::move(tick_clock)); } } // namespace ui
diff --git a/ui/events/x/events_x_utils.h b/ui/events/x/events_x_utils.h index 4d5e7544..64814e87 100644 --- a/ui/events/x/events_x_utils.h +++ b/ui/events/x/events_x_utils.h
@@ -89,8 +89,7 @@ // Uses the XModifierStateWatcher to determine if alt is pressed or not. EVENTS_X_EXPORT bool IsAltPressed(); -EVENTS_X_EXPORT void ResetTimestampRolloverCountersForTesting( - std::unique_ptr<base::TickClock> tick_clock = nullptr); +EVENTS_X_EXPORT void ResetTimestampRolloverCountersForTesting(); } // namespace ui
diff --git a/ui/gfx/color_palette.h b/ui/gfx/color_palette.h index 3c77e6a..22b2f6f 100644 --- a/ui/gfx/color_palette.h +++ b/ui/gfx/color_palette.h
@@ -13,8 +13,6 @@ // as a visual flag for misbehaving code. constexpr SkColor kPlaceholderColor = SK_ColorRED; -constexpr SkColor kChromeIconGrey = SkColorSetRGB(0x5A, 0x5A, 0x5A); - // The number refers to the shade of darkness. Each color in the MD // palette ranges from 100-900. constexpr SkColor kGoogleBlue300 = SkColorSetRGB(0x8A, 0xB4, 0xF8); @@ -38,6 +36,13 @@ constexpr SkColor kGoogleGrey700 = SkColorSetRGB(0x5F, 0x63, 0x68); constexpr SkColor kGoogleGrey800 = SkColorSetRGB(0x3C, 0x40, 0x43); constexpr SkColor kGoogleGrey900 = SkColorSetRGB(0x20, 0x21, 0x24); +constexpr SkColor kPaperGrey600 = SkColorSetRGB(0x75, 0x75, 0x75); + +// kChromeIconGrey is subject to change in the future, kPaperGrey600 is set in +// stone. If you're semantically looking for "the icon color Chrome uses" then +// use kChromeIconGrey, if you're looking for paper grey specifically, use the +// paper-grey constant directly. +constexpr SkColor kChromeIconGrey = kPaperGrey600; // An alpha value for designating a control's disabled state. In specs this is // sometimes listed as 0.38a.
diff --git a/ui/keyboard/container_floating_behavior.cc b/ui/keyboard/container_floating_behavior.cc index 7939ecf..855cdc20 100644 --- a/ui/keyboard/container_floating_behavior.cc +++ b/ui/keyboard/container_floating_behavior.cc
@@ -93,27 +93,17 @@ int top_distance = keyboard_bounds.y(); int bottom_distance = screen_size.height() - (keyboard_bounds.bottom()); + double available_width = left_distance + right_distance; + double available_height = top_distance + bottom_distance; + if (!default_position_) { default_position_ = std::make_unique<KeyboardPosition>(); } - if (left_distance < right_distance) { - default_position_->horizontal_anchor_direction = - HorizontalAnchorDirection::LEFT; - default_position_->offset.set_x(left_distance); - } else { - default_position_->horizontal_anchor_direction = - HorizontalAnchorDirection::RIGHT; - default_position_->offset.set_x(right_distance); - } - if (top_distance < bottom_distance) { - default_position_->vertical_anchor_direction = VerticalAnchorDirection::TOP; - default_position_->offset.set_y(top_distance); - } else { - default_position_->vertical_anchor_direction = - VerticalAnchorDirection::BOTTOM; - default_position_->offset.set_y(bottom_distance); - } + default_position_->left_padding_allotment_ratio = + left_distance / available_width; + default_position_->top_padding_allotment_ratio = + top_distance / available_height; } gfx::Rect ContainerFloatingBehavior::ContainKeyboardToScreenBounds( @@ -162,19 +152,12 @@ top_left_offset.set_y(display_bounds.height() - keyboard_size.height() - kDefaultDistanceFromScreenBottom); } else { - if (position->horizontal_anchor_direction == - HorizontalAnchorDirection::LEFT) { - top_left_offset.set_x(position->offset.x()); - } else { - top_left_offset.set_x(display_bounds.width() - position->offset.x() - - keyboard_size.width()); - } - if (position->vertical_anchor_direction == VerticalAnchorDirection::TOP) { - top_left_offset.set_y(position->offset.y()); - } else { - top_left_offset.set_y(display_bounds.height() - position->offset.y() - - keyboard_size.height()); - } + double left = (display_bounds.width() - keyboard_size.width()) * + position->left_padding_allotment_ratio; + double top = (display_bounds.height() - keyboard_size.height()) * + position->top_padding_allotment_ratio; + top_left_offset.set_x((int)left); + top_left_offset.set_y((int)top); } // Make sure that this location is valid according to the current size of the
diff --git a/ui/keyboard/container_floating_behavior.h b/ui/keyboard/container_floating_behavior.h index 6247b7d8..6ea2b2a 100644 --- a/ui/keyboard/container_floating_behavior.h +++ b/ui/keyboard/container_floating_behavior.h
@@ -23,23 +23,9 @@ constexpr int kDefaultDistanceFromScreenBottom = 20; constexpr int kDefaultDistanceFromScreenRight = 20; -enum class HorizontalAnchorDirection { - LEFT, - RIGHT, -}; - -enum class VerticalAnchorDirection { - TOP, - BOTTOM, -}; - struct KeyboardPosition { - // Whether the keyboard is anchored to the left or right side of the screen. - HorizontalAnchorDirection horizontal_anchor_direction; - // Whether the keyboard is anchored to the top or bottom side of the screen. - VerticalAnchorDirection vertical_anchor_direction; - // Distance from the sides of the screen that the keyboard is anchored to. - gfx::Point offset; + double left_padding_allotment_ratio; + double top_padding_allotment_ratio; }; class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior {
diff --git a/ui/keyboard/container_floating_behavior_unittest.cc b/ui/keyboard/container_floating_behavior_unittest.cc index b8421fa..6db3b40 100644 --- a/ui/keyboard/container_floating_behavior_unittest.cc +++ b/ui/keyboard/container_floating_behavior_unittest.cc
@@ -62,6 +62,7 @@ gfx::Rect top_right(900, 0, keyboard_width, keyboard_height); gfx::Rect bottom_left(0, 400, keyboard_width, keyboard_height); gfx::Rect bottom_right(900, 400, keyboard_width, keyboard_height); + gfx::Rect bottomish_center(450, 390, keyboard_width, keyboard_height); // Save an arbitrary position so that default location will not be used. floating_behavior.SavePosition( @@ -98,6 +99,18 @@ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size, workspace_tall); ASSERT_EQ(gfx::Point(400, 900), result); + + floating_behavior.AdjustSetBoundsRequest(workspace_wide, bottomish_center); + result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size, + workspace_wide); + ASSERT_EQ(gfx::Point(450, 390), result); + result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size, + workspace_tall); + + // rather than 400:0 for the vertical padding, use 390:10 + // with 900 pixels available this ratio results in 877.5, which is truncated. + // 390 / 400 * 900 = 877.5 + ASSERT_EQ(gfx::Point(200, 877), result); } TEST(ContainerFloatingBehaviorTest, DontSaveCoordinatesUntilKeyboardMoved) {
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 83d5d1d..3e0b41a4 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -352,6 +352,19 @@ </if> + <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU" desc="The name of the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> + Writing Direction + </message> + <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT" desc="The name of the 'default' item from the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> + Default + </message> + <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR" desc="The name of the 'Left to Right' item from the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> + Left to Right + </message> + <message name="IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL" desc="The name of the 'Right to Left' item from the Writing Direction submenu in the content area context menu. To translate, launch /Applications/TextEdit.app in an appropriately localized version of OS X, right-click on the text entry area and use the translation from there."> + Right to Left + </message> + <!-- File chooser dialog default titles (only used on Linux) --> <message name="IDS_SELECT_FOLDER_DIALOG_TITLE" desc="The default title for the Select Folder file chooser dialog."> Select Folder
diff --git a/ui/views/controls/button/image_button_factory.cc b/ui/views/controls/button/image_button_factory.cc index 6e7ddda2..2ae7198 100644 --- a/ui/views/controls/button/image_button_factory.cc +++ b/ui/views/controls/button/image_button_factory.cc
@@ -32,7 +32,10 @@ SkColor related_text_color) { const SkColor icon_color = color_utils::DeriveDefaultIconColor(related_text_color); - const SkColor disabled_color = SkColorSetA(icon_color, 0xff / 2); + // DeriveDefaultIconColor is set up to spit out #757575 from black. Applying + // 0xB3 as alpha results in the desired #9E9E9E disabled color when rendered + // against a white background. + const SkColor disabled_color = SkColorSetA(icon_color, 0xB3); button->SetImage(Button::STATE_NORMAL, gfx::CreateVectorIcon(icon, icon_color)); button->SetImage(Button::STATE_DISABLED,
diff --git a/ui/views/controls/textfield/textfield_test_api.cc b/ui/views/controls/textfield/textfield_test_api.cc index bef918a..3f756df 100644 --- a/ui/views/controls/textfield/textfield_test_api.cc +++ b/ui/views/controls/textfield/textfield_test_api.cc
@@ -5,6 +5,7 @@ #include "ui/views/controls/textfield/textfield_test_api.h" #include "ui/gfx/geometry/rect.h" +#include "ui/views/controls/views_text_services_context_menu.h" namespace views { @@ -33,4 +34,10 @@ textfield_->cursor_view_.SetBoundsRect(bounds); } +bool TextfieldTestApi::IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection direction) const { + return ViewsTextServicesContextMenu::IsTextDirectionCheckedForTesting( + textfield_->text_services_context_menu_.get(), direction); +} + } // namespace views
diff --git a/ui/views/controls/textfield/textfield_test_api.h b/ui/views/controls/textfield/textfield_test_api.h index 8b898715..c111175e 100644 --- a/ui/views/controls/textfield/textfield_test_api.h +++ b/ui/views/controls/textfield/textfield_test_api.h
@@ -5,6 +5,7 @@ #ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_TEST_API_H_ #define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_TEST_API_H_ +#include "base/i18n/rtl.h" #include "base/macros.h" #include "ui/views/controls/textfield/textfield.h" @@ -50,6 +51,9 @@ bool IsCursorVisible() const { return textfield_->cursor_view_.visible(); } + bool IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection direction) const; + private: Textfield* textfield_;
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc index 59f8c78..5cfb980 100644 --- a/ui/views/controls/textfield/textfield_unittest.cc +++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -3405,4 +3405,37 @@ EXPECT_EQ(ui::EF_SHIFT_DOWN, textfield_->event_flags()); } +#if defined(OS_MACOSX) +// Tests to see if the BiDi submenu items are updated correctly when the +// textfield's text direction is changed. +TEST_F(TextfieldTest, TextServicesContextMenuTextDirectionTest) { + InitTextfield(); + EXPECT_TRUE(textfield_->context_menu_controller()); + + EXPECT_TRUE(GetContextMenuModel()); + + textfield_->ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection::LEFT_TO_RIGHT); + test_api_->UpdateContextMenu(); + + EXPECT_FALSE(test_api_->IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection::UNKNOWN_DIRECTION)); + EXPECT_TRUE(test_api_->IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection::LEFT_TO_RIGHT)); + EXPECT_FALSE(test_api_->IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection::RIGHT_TO_LEFT)); + + textfield_->ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection::RIGHT_TO_LEFT); + test_api_->UpdateContextMenu(); + + EXPECT_FALSE(test_api_->IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection::UNKNOWN_DIRECTION)); + EXPECT_FALSE(test_api_->IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection::LEFT_TO_RIGHT)); + EXPECT_TRUE(test_api_->IsTextDirectionCheckedInContextMenu( + base::i18n::TextDirection::RIGHT_TO_LEFT)); +} +#endif // defined(OS_MACOSX) + } // namespace views
diff --git a/ui/views/controls/views_text_services_context_menu.cc b/ui/views/controls/views_text_services_context_menu.cc index e7a41a2..ec59753 100644 --- a/ui/views/controls/views_text_services_context_menu.cc +++ b/ui/views/controls/views_text_services_context_menu.cc
@@ -4,6 +4,8 @@ #include "ui/views/controls/views_text_services_context_menu.h" +#include "base/logging.h" + namespace views { // static @@ -13,4 +15,11 @@ return nullptr; } +bool ViewsTextServicesContextMenu::IsTextDirectionCheckedForTesting( + ViewsTextServicesContextMenu* menu, + base::i18n::TextDirection direction) { + NOTREACHED(); + return false; +} + } // namespace views \ No newline at end of file
diff --git a/ui/views/controls/views_text_services_context_menu.h b/ui/views/controls/views_text_services_context_menu.h index 78a9348..2388b27 100644 --- a/ui/views/controls/views_text_services_context_menu.h +++ b/ui/views/controls/views_text_services_context_menu.h
@@ -7,6 +7,9 @@ #include <memory> +#include "base/i18n/rtl.h" +#include "ui/views/views_export.h" + namespace ui { class SimpleMenuModel; } @@ -25,6 +28,12 @@ static std::unique_ptr<ViewsTextServicesContextMenu> Create( ui::SimpleMenuModel* menu, Textfield* textfield); + + // Method for testing. Returns true if the text direction BiDi submenu item + // in |menu| should be checked. + VIEWS_EXPORT static bool IsTextDirectionCheckedForTesting( + ViewsTextServicesContextMenu* menu, + base::i18n::TextDirection direction); }; } // namespace views
diff --git a/ui/views/controls/views_text_services_context_menu_mac.mm b/ui/views/controls/views_text_services_context_menu_mac.mm index 8e8036a..129f059f 100644 --- a/ui/views/controls/views_text_services_context_menu_mac.mm +++ b/ui/views/controls/views_text_services_context_menu_mac.mm
@@ -24,6 +24,7 @@ ViewsTextServicesContextMenuMac(ui::SimpleMenuModel* menu, Textfield* client) : text_services_menu_(this), client_(client) { text_services_menu_.AppendToContextMenu(menu); + text_services_menu_.AppendEditableItems(menu); } ~ViewsTextServicesContextMenuMac() override {} @@ -33,6 +34,26 @@ return client_->GetSelectedText(); } + bool IsTextDirectionEnabled( + base::i18n::TextDirection direction) const override { + return direction != base::i18n::UNKNOWN_DIRECTION; + } + + bool IsTextDirectionChecked( + base::i18n::TextDirection direction) const override { + return direction != base::i18n::UNKNOWN_DIRECTION && + client_->GetTextDirection() == direction; + } + + void UpdateTextDirection(base::i18n::TextDirection direction) override { + DCHECK_NE(direction, base::i18n::UNKNOWN_DIRECTION); + + base::i18n::TextDirection text_direction = + direction == base::i18n::LEFT_TO_RIGHT ? base::i18n::LEFT_TO_RIGHT + : base::i18n::RIGHT_TO_LEFT; + client_->ChangeTextDirectionAndLayoutAlignment(text_direction); + } + private: // Appends and handles the text service menu. ui::TextServicesContextMenu text_services_menu_; @@ -52,4 +73,11 @@ return base::MakeUnique<ViewsTextServicesContextMenuMac>(menu, client); } +// static +bool ViewsTextServicesContextMenu::IsTextDirectionCheckedForTesting( + ViewsTextServicesContextMenu* menu, + base::i18n::TextDirection direction) { + return static_cast<views::ViewsTextServicesContextMenuMac*>(menu) + ->IsTextDirectionChecked(direction); +} } // namespace views \ No newline at end of file
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn index a06384a..a8e4c99 100644 --- a/ui/views/mus/BUILD.gn +++ b/ui/views/mus/BUILD.gn
@@ -250,6 +250,7 @@ "//ui/aura", "//ui/aura:test_support", "//ui/base", + "//ui/base:test_support", "//ui/base/ime", "//ui/events:events_base", "//ui/events:test_support",
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc index 91d33acb..9399f82 100644 --- a/ui/views/mus/mus_client.cc +++ b/ui/views/mus/mus_client.cc
@@ -195,6 +195,12 @@ properties[WindowManager::kRemoveStandardFrame_InitProperty] = mojo::ConvertTo<TransportType>(init_params.remove_standard_frame); + if (init_params.corner_radius) { + properties[WindowManager::kWindowCornerRadius_Property] = + mojo::ConvertTo<TransportType>( + static_cast<PrimitiveType>(*init_params.corner_radius)); + } + if (!Widget::RequiresNonClientView(init_params.type)) return properties;
diff --git a/ui/views/test/views_test_base.h b/ui/views/test/views_test_base.h index af9760e..7702736 100644 --- a/ui/views/test/views_test_base.h +++ b/ui/views/test/views_test_base.h
@@ -41,7 +41,7 @@ // Creates a widget of |type| with any platform specific data for use in // cross-platform tests. - Widget::InitParams CreateParams(Widget::InitParams::Type type); + virtual Widget::InitParams CreateParams(Widget::InitParams::Type type); bool HasCompositingManager() const;
diff --git a/ui/views/test/widget_test.h b/ui/views/test/widget_test.h index 8e496f1..09748e7 100644 --- a/ui/views/test/widget_test.h +++ b/ui/views/test/widget_test.h
@@ -100,6 +100,11 @@ // Return true if |window| is transparent according to the native platform. static bool IsNativeWindowTransparent(gfx::NativeWindow window); + // Returns whether |widget| has a Window shadow managed in this process. That + // is, a shadow that is drawn outside of the Widget bounds, and managed by the + // WindowManager. + static bool WidgetHasInProcessShadow(Widget* widget); + // Returns the set of all Widgets that currently have a NativeWindow. static Widget::Widgets GetAllWidgets();
diff --git a/ui/views/test/widget_test_aura.cc b/ui/views/test/widget_test_aura.cc index 45104b36..92d65db 100644 --- a/ui/views/test/widget_test_aura.cc +++ b/ui/views/test/widget_test_aura.cc
@@ -13,6 +13,7 @@ #include "ui/aura/window_tree_host.h" #include "ui/views/mus/mus_client.h" #include "ui/views/widget/widget.h" +#include "ui/wm/core/shadow_controller.h" #if defined(USE_X11) #include "ui/gfx/x/x11.h" // nogncheck @@ -163,6 +164,21 @@ } // static +bool WidgetTest::WidgetHasInProcessShadow(Widget* widget) { + aura::Window* window = widget->GetNativeWindow(); + if (wm::ShadowController::GetShadowForWindow(window)) + return true; + + // If the Widget's native window is the content window for a + // DesktopWindowTreeHost, then giving the root window a shadow also has the + // effect of drawing a shadow around the window. + if (window->parent() == window->GetRootWindow()) + return wm::ShadowController::GetShadowForWindow(window->GetRootWindow()); + + return false; +} + +// static Widget::Widgets WidgetTest::GetAllWidgets() { Widget::Widgets all_widgets; for (aura::Window* window : GetAllTopLevelWindows())
diff --git a/ui/views/test/widget_test_mac.mm b/ui/views/test/widget_test_mac.mm index af3f4923..c663b4e9 100644 --- a/ui/views/test/widget_test_mac.mm +++ b/ui/views/test/widget_test_mac.mm
@@ -90,6 +90,11 @@ } // static +bool WidgetTest::WidgetHasInProcessShadow(Widget* widget) { + return false; +} + +// static Widget::Widgets WidgetTest::GetAllWidgets() { Widget::Widgets all_widgets; for (NSWindow* window : [NSApp windows]) {
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 02fb4e32..a9be3ab 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc
@@ -157,15 +157,23 @@ // MusClient has assertions that ui::mojom::WindowType matches // views::Widget::InitParams::Type. aura::SetWindowType(window_, static_cast<ui::mojom::WindowType>(params.type)); + if (params.corner_radius) { + window_->SetProperty(aura::client::kWindowCornerRadiusKey, + *params.corner_radius); + } window_->SetProperty(aura::client::kShowStateKey, params.show_state); if (params.type == Widget::InitParams::TYPE_BUBBLE) wm::SetHideOnDeactivate(window_, true); window_->SetTransparent( params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW); + + // Check for SHADOW_TYPE_NONE before aura::Window::Init() to ensure observers + // do not add useless shadow layers by deriving one from the window type. + SetShadowElevationFromInitParams(window_, params); + window_->Init(params.layer_type); // Set name after layer init so it propagates to layer. window_->SetName(params.name); - SetShadowElevationFromInitParams(window_, params); if (params.type == Widget::InitParams::TYPE_CONTROL) window_->Show();
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 10fd33a7..6c0c6080 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -240,6 +240,8 @@ // A hint about the size of the shadow if the type is SHADOW_TYPE_DROP. May // be ignored on some platforms. No value indicates no preference. base::Optional<int> shadow_elevation; + // The window corner radius. May be ignored on some platforms. + base::Optional<int> corner_radius; // Specifies that the system default caption and icon should not be // rendered, and that the client area should be equivalent to the window // area. Only used on some platforms (Windows and Linux).
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc index c22c91865..3fb031ef 100644 --- a/ui/views/widget/widget_interactive_uitest.cc +++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -14,11 +14,13 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/win/windows_version.h" #include "build/build_config.h" #include "mojo/edk/embedder/embedder.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/base/test/ui_controls.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" #include "ui/events/event_processor.h" @@ -362,6 +364,74 @@ widget2->CloseNow(); widget1->CloseNow(); } + +class TouchEventHandler : public ui::EventHandler { + public: + TouchEventHandler(Widget* widget) : widget_(widget) { + widget_->GetNativeWindow()->GetHost()->window()->AddPreTargetHandler(this); + } + + ~TouchEventHandler() override { + widget_->GetNativeWindow()->GetHost()->window()->RemovePreTargetHandler( + this); + } + + void WaitForEvents() { + base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); + base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop); + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + static void __stdcall AsyncActivateMouse(HWND hwnd, + UINT msg, + ULONG_PTR data, + LRESULT result) { + EXPECT_EQ(MA_NOACTIVATE, result); + std::move(reinterpret_cast<TouchEventHandler*>(data)->quit_closure_).Run(); + } + + void ActivateViaMouse() { + SendMessageCallback( + widget_->GetNativeWindow()->GetHost()->GetAcceleratedWidget(), + WM_MOUSEACTIVATE, 0, 0, AsyncActivateMouse, + reinterpret_cast<ULONG_PTR>(this)); + } + + private: + // ui::EventHandler: + void OnTouchEvent(ui::TouchEvent* event) override { + if (event->type() == ui::ET_TOUCH_PRESSED) + ActivateViaMouse(); + } + + Widget* widget_; + base::OnceClosure quit_closure_; + DISALLOW_COPY_AND_ASSIGN(TouchEventHandler); +}; + +TEST_F(WidgetTestInteractive, TouchNoActivateWindow) { + // ui_controls::SendTouchEvents which uses InjectTouchInput API only works + // on Windows 8 and up. + if (base::win::GetVersion() <= base::win::VERSION_WIN7) + return; + + View* focusable_view = new View; + focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS); + Widget* widget = CreateWidget(); + widget->GetContentsView()->AddChildView(focusable_view); + widget->Show(); + + { + TouchEventHandler touch_event_handler(widget); + ASSERT_TRUE(ui_controls::SendTouchEvents(ui_controls::PRESS, 1, 100, 100)); + touch_event_handler.WaitForEvents(); + } + + widget->CloseNow(); +} + #endif // defined(OS_WIN) TEST_F(WidgetTestInteractive, CaptureAutoReset) {
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index d03f648..76a9b283 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc
@@ -47,6 +47,12 @@ #include "base/mac/mac_util.h" #endif +#if defined(OS_CHROMEOS) +#include "ui/wm/core/base_focus_rules.h" +#include "ui/wm/core/focus_controller.h" +#include "ui/wm/core/shadow_controller.h" +#endif + namespace views { namespace test { @@ -3731,6 +3737,142 @@ EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSEWHEEL)); } +class WidgetShadowTest : public WidgetTest { + public: + WidgetShadowTest() { InitControllers(); } + + // WidgetTest: + Widget::InitParams CreateParams(Widget::InitParams::Type type) override { + Widget::InitParams params = + WidgetTest::CreateParams(override_type_.value_or(type)); + params.shadow_type = Widget::InitParams::SHADOW_TYPE_DROP; + params.shadow_elevation = 10; + params.name = name_; + params.child = force_child_; + return params; + } + + protected: + base::Optional<Widget::InitParams::Type> override_type_; + std::string name_; + bool force_child_ = false; + + private: +#if !defined(OS_CHROMEOS) + void InitControllers() {} +#else + class TestFocusRules : public wm::BaseFocusRules { + public: + TestFocusRules() = default; + + bool SupportsChildActivation(aura::Window* window) const override { + return true; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestFocusRules); + }; + + void InitControllers() { + // Add bits usually managed by the ash::Shell. Under Mus, + // DesktopNativeWidgetAura provides these in-process instead. + if (IsMus()) + return; + + focus_controller_ = + std::make_unique<wm::FocusController>(new TestFocusRules); + shadow_controller_ = + std::make_unique<wm::ShadowController>(focus_controller_.get()); + } + + std::unique_ptr<wm::FocusController> focus_controller_; + std::unique_ptr<wm::ShadowController> shadow_controller_; +#endif // OS_CHROMEOS + + DISALLOW_COPY_AND_ASSIGN(WidgetShadowTest); +}; + +// Disabled on Mac: All drop shadows are managed out of process for now. +#if defined(OS_MACOSX) && !defined(USE_AURA) +#define MAYBE_ShadowsInRootWindow DISABLED_ShadowsInRootWindow +#else +#define MAYBE_ShadowsInRootWindow ShadowsInRootWindow +#endif + +// Test that shadows are not added to root windows when created or upon +// activation. Test that shadows are added to non-root windows even if not +// activated. +TEST_F(WidgetShadowTest, MAYBE_ShadowsInRootWindow) { + // A desktop window clips to its bounds, so it shouldn't have a shadow. + bool top_level_window_should_have_shadow = false; + +#if defined(OS_CHROMEOS) + // In Mus, the shadow should be in the WindowServer process only. In non-mus + // CreateNativeDesktopWidget() creates a non-root window, so it should have + // a shadow. + top_level_window_should_have_shadow = !IsMus(); +#endif + + // To start, just create a Widget. This constructs the first ShadowController + // which will start observing the environment for additional aura::Window + // initialization. The very first ShadowController in DesktopNativeWidgetAura + // is created after the call to aura::Window::Init(), so the ShadowController + // Impl class won't ever see this first Window being initialized. + name_ = "other_top_level"; + Widget* other_top_level = CreateNativeDesktopWidget(); + + name_ = "top_level"; + Widget* top_level = CreateNativeDesktopWidget(); + top_level->SetBounds(gfx::Rect(100, 100, 320, 200)); + + EXPECT_FALSE(WidgetHasInProcessShadow(top_level)); + EXPECT_FALSE(top_level->IsVisible()); + top_level->ShowInactive(); + EXPECT_EQ(top_level_window_should_have_shadow, + WidgetHasInProcessShadow(top_level)); + top_level->Show(); + EXPECT_EQ(top_level_window_should_have_shadow, + WidgetHasInProcessShadow(top_level)); + + name_ = "control"; + Widget* control = CreateChildNativeWidgetWithParent(top_level); + control->SetBounds(gfx::Rect(20, 20, 160, 100)); + + // Widgets of TYPE_CONTROL become visible during Init, so start with a shadow. + EXPECT_TRUE(WidgetHasInProcessShadow(control)); + control->ShowInactive(); + EXPECT_TRUE(WidgetHasInProcessShadow(control)); + control->Show(); + EXPECT_TRUE(WidgetHasInProcessShadow(control)); + + name_ = "child"; + override_type_ = Widget::InitParams::TYPE_POPUP; + force_child_ = true; + Widget* child = CreateChildNativeWidgetWithParent(top_level); + child->SetBounds(gfx::Rect(20, 20, 160, 100)); + + // Now false: the Widget hasn't been shown yet. + EXPECT_FALSE(WidgetHasInProcessShadow(child)); + child->ShowInactive(); + EXPECT_TRUE(WidgetHasInProcessShadow(child)); + child->Show(); + EXPECT_TRUE(WidgetHasInProcessShadow(child)); + + other_top_level->Show(); + + // Re-activate the top level window. This handles a hypothetical case where + // a shadow is added via the ActivationChangeObserver rather than by the + // aura::WindowObserver. Activation changes only modify an existing shadow + // (if there is one), but should never install a Shadow, even if the Window + // properties otherwise say it should have one. + top_level->Show(); + EXPECT_EQ(top_level_window_should_have_shadow, + WidgetHasInProcessShadow(top_level)); + + top_level->Close(); + other_top_level->Close(); +} + #if defined(OS_WIN) namespace {
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 81a43f79..c8fb7eec 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -2751,6 +2751,17 @@ return 0; } + // Increment |touch_down_contexts_| on a pointer down. This variable + // is used to debounce the WM_MOUSEACTIVATE events. + if (message == WM_POINTERDOWN) { + touch_down_contexts_++; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&HWNDMessageHandler::ResetTouchDownContext, + weak_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(kTouchDownContextResetTimeout)); + } + size_t mapped_pointer_id = id_generator_.GetGeneratedID(pointer_id); POINTER_INFO pointer_info = pointer_touch_info.pointerInfo; POINT client_point = pointer_info.ptPixelLocationRaw; @@ -2792,23 +2803,8 @@ if (event_type == ui::ET_TOUCH_RELEASED) id_generator_.ReleaseNumber(pointer_id); - if (ref) { - bool handled = event.handled(); - - // For events that are unhandled, perform a hit test to see if they - // are inside the client area. If they are indicate that they've already - // been handled because we don't want Windows to dispatch compatibility - // events for these since we've already dispatched a ui::Event for them. - if (!handled) { - LPARAM l_param_ht = MAKELPARAM(pointer_info.ptPixelLocationRaw.x, - pointer_info.ptPixelLocationRaw.y); - LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht); - - if (hittest == HTCLIENT) - handled = true; - } - SetMsgHandled(handled); - } + if (ref) + SetMsgHandled(event.handled()); return 0; }
diff --git a/ui/webui/resources/cr_elements/search_highlight_style_css.html b/ui/webui/resources/cr_elements/search_highlight_style_css.html new file mode 100644 index 0000000..451f86d --- /dev/null +++ b/ui/webui/resources/cr_elements/search_highlight_style_css.html
@@ -0,0 +1,48 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="shared_vars_css.html"> + +<dom-module id="search-highlight-style"> + <template> + <style> + .search-bubble { + /* RGB value matches var(--paper-yellow-500). */ + --search-bubble-color: rgba(255, 235, 59, 0.9); + position: absolute; + z-index: 1; + } + + .search-bubble-innards { + align-items: center; + background-color: var(--search-bubble-color); + border-radius: 2px; + max-width: 100px; + min-width: 64px; + padding: 4px 10px; + text-align: center; + @apply --cr-text-elide; + } + + /* Provides the arrow which points at the anchor element. */ + .search-bubble-innards::after { + background-color: var(--search-bubble-color); + content: ''; + height: 10px; + left: calc(50% - 5px); + position: absolute; + top: -5px; + transform: rotate(-45deg); + width: 10px; + z-index: -1; + } + + /* Turns the arrow direction downwards, when the bubble is placed above + * the anchor element */ + .search-bubble-innards.above::after { + bottom: -5px; + top: auto; + transform: rotate(-135deg); + } + </style> + </template> +</dom-module>
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html index 83d28f6..f7eeb88 100644 --- a/ui/webui/resources/cr_elements/shared_vars_css.html +++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -67,6 +67,12 @@ padding: 0 var(--cr-section-padding); }; + --cr-text-elide: { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + }; + --cr-title-text: { color: rgb(90, 90, 90); font-size: 107.6923%; /* Go to 14px from 13px. */
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp index c5c6122..c348d34f 100644 --- a/ui/webui/resources/cr_elements_resources.grdp +++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -284,6 +284,10 @@ file="../../webui/resources/cr_elements/paper_toggle_style_css.html" type="chrome_html" compress="gzip" /> + <structure name="IDR_CR_ELEMENTS_SEARCH_HIGHLIGHT_STYLE_CSS_HTML" + file="../../webui/resources/cr_elements/search_highlight_style_css.html" + type="chrome_html" + compress="gzip" /> <structure name="IDR_CR_ELEMENTS_CR_SHARED_VARS_CSS_HTML" file="../../webui/resources/cr_elements/shared_vars_css.html" type="chrome_html"
diff --git a/ui/webui/resources/js/search_highlight_utils.js b/ui/webui/resources/js/search_highlight_utils.js index 6c552ea..d7bf3c8a 100644 --- a/ui/webui/resources/js/search_highlight_utils.js +++ b/ui/webui/resources/js/search_highlight_utils.js
@@ -12,6 +12,9 @@ /** @type {string} */ const HIT_CSS_CLASS = 'search-highlight-hit'; + /** @type {string} */ + const SEARCH_BUBBLE_CSS_CLASS = 'search-bubble'; + /** * Applies the highlight UI (yellow rectangle) around all matches in |node|. * @param {!Node} node The text node to be highlighted. |node| ends up @@ -59,18 +62,69 @@ * @private */ function findAndRemoveHighlights(node) { - const wrappers = node.querySelectorAll('* /deep/ .' + WRAPPER_CSS_CLASS); + const wrappers = node.querySelectorAll(`* /deep/ .${WRAPPER_CSS_CLASS}`); for (let i = 0; i < wrappers.length; i++) { const wrapper = wrappers[i]; const originalNode = - wrapper.querySelector('.' + ORIGINAL_CONTENT_CSS_CLASS); + wrapper.querySelector(`.${ORIGINAL_CONTENT_CSS_CLASS}`); wrapper.parentElement.replaceChild(originalNode.firstChild, wrapper); } } + /** + * Finds and removes all previously created yellow search bubbles under + * |node| (both within self and children's Shadow DOM). + * @param {!Node} node + * @private + */ + function findAndRemoveBubbles(node) { + const searchBubbles = + node.querySelectorAll(`* /deep/ .${SEARCH_BUBBLE_CSS_CLASS}`); + for (let bubble of searchBubbles) + bubble.remove(); + } + + /** + * Highlights an HTML element by displaying a search bubble. The element + * should already be visible or the bubble will render incorrectly. + * @param {!HTMLElement} element The element to be highlighted. + * @param {string} rawQuery The search query. + * @private + */ + function highlightControlWithBubble(element, rawQuery) { + let searchBubble = element.querySelector(`.${SEARCH_BUBBLE_CSS_CLASS}`); + // If the element has already been highlighted, there is no need to do + // anything. + if (searchBubble) + return; + + searchBubble = document.createElement('div'); + searchBubble.classList.add(SEARCH_BUBBLE_CSS_CLASS); + const innards = document.createElement('div'); + innards.classList.add('search-bubble-innards'); + innards.textContent = rawQuery; + searchBubble.appendChild(innards); + element.appendChild(searchBubble); + + const updatePosition = function() { + searchBubble.style.top = element.offsetTop + + (innards.classList.contains('above') ? -searchBubble.offsetHeight : + element.offsetHeight) + + 'px'; + }; + updatePosition(); + + searchBubble.addEventListener('mouseover', function() { + innards.classList.toggle('above'); + updatePosition(); + }); + } + return { highlight: highlight, + highlightControlWithBubble: highlightControlWithBubble, + findAndRemoveBubbles: findAndRemoveBubbles, findAndRemoveHighlights: findAndRemoveHighlights, }; });
diff --git a/ui/wm/core/shadow_controller.cc b/ui/wm/core/shadow_controller.cc index 350359aa..875ed5e9 100644 --- a/ui/wm/core/shadow_controller.cc +++ b/ui/wm/core/shadow_controller.cc
@@ -105,6 +105,7 @@ void OnWindowPropertyChanged(aura::Window* window, const void* key, intptr_t old) override; + void OnWindowVisibilityChanging(aura::Window* window, bool visible) override; void OnWindowBoundsChanged(aura::Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, @@ -157,24 +158,45 @@ } void ShadowController::Impl::OnWindowInitialized(aura::Window* window) { + // During initialization, the window can't reliably tell whether it will be a + // root window. That must be checked in the first visibility change + DCHECK(!window->parent()); + DCHECK(!window->TargetVisibility()); observer_manager_.Add(window); - HandlePossibleShadowVisibilityChange(window); } void ShadowController::Impl::OnWindowPropertyChanged(aura::Window* window, const void* key, intptr_t old) { - if (key == kShadowElevationKey) { - if (window->GetProperty(kShadowElevationKey) == old) - return; - } else if (key == aura::client::kShowStateKey) { - if (window->GetProperty(aura::client::kShowStateKey) == - static_cast<ui::WindowShowState>(old)) { - return; - } - } else { + bool shadow_will_change = false; + if (key == kShadowElevationKey) + shadow_will_change = window->GetProperty(kShadowElevationKey) != old; + + if (key == aura::client::kShowStateKey) { + shadow_will_change = window->GetProperty(aura::client::kShowStateKey) != + static_cast<ui::WindowShowState>(old); + } + + // Check the target visibility. IsVisible() may return false if a parent layer + // is hidden, but |this| only observes calls to Show()/Hide() on |window|. + if (shadow_will_change && window->TargetVisibility()) + HandlePossibleShadowVisibilityChange(window); +} + +void ShadowController::Impl::OnWindowVisibilityChanging(aura::Window* window, + bool visible) { + // At the time of the first visibility change, |window| will give a correct + // answer for whether or not it is a root window. If it is, don't bother + // observing: a shadow should never be added. Root windows can only have + // shadows in the WindowServer (where a corresponding aura::Window may no + // longer be a root window). Without this check, a second shadow is added, + // which clips to the root window bounds; filling any rounded corners the + // window may have. + if (window->IsRootWindow()) { + observer_manager_.Remove(window); return; } + HandlePossibleShadowVisibilityChange(window); } @@ -220,7 +242,7 @@ return false; } - return static_cast<int>(GetShadowElevationConvertDefault(window)) > 0; + return GetShadowElevationConvertDefault(window) > 0; } void ShadowController::Impl::HandlePossibleShadowVisibilityChange( @@ -236,12 +258,19 @@ } void ShadowController::Impl::CreateShadowForWindow(aura::Window* window) { + DCHECK(!window->IsRootWindow()); Shadow* shadow = new Shadow(); window->SetProperty(kShadowLayerKey, shadow); + + int corner_radius = window->GetProperty(aura::client::kWindowCornerRadiusKey); + if (corner_radius >= 0) + shadow->SetRoundedCornerRadius(corner_radius); + shadow->Init(GetShadowElevationForActiveState(window)); shadow->SetContentBounds(gfx::Rect(window->bounds().size())); shadow->layer()->SetVisible(ShouldShowShadowForWindow(window)); window->layer()->Add(shadow->layer()); + window->layer()->StackAtBottom(shadow->layer()); } ShadowController::Impl::Impl()
diff --git a/ui/wm/core/shadow_controller_unittest.cc b/ui/wm/core/shadow_controller_unittest.cc index 9e51c6b..c3af569 100644 --- a/ui/wm/core/shadow_controller_unittest.cc +++ b/ui/wm/core/shadow_controller_unittest.cc
@@ -61,15 +61,16 @@ window->Init(ui::LAYER_TEXTURED); ParentWindow(window.get()); - // We should create the shadow before the window is visible (the shadow's - // layer won't get drawn yet since it's a child of the window's layer). + // The shadow is not created until the Window is shown (some Windows should + // never get shadows, which is checked when the window first becomes visible). + EXPECT_FALSE(ShadowController::GetShadowForWindow(window.get())); + window->Show(); + const Shadow* shadow = ShadowController::GetShadowForWindow(window.get()); ASSERT_TRUE(shadow != NULL); EXPECT_TRUE(shadow->layer()->visible()); // The shadow should remain visible after window visibility changes. - window->Show(); - EXPECT_TRUE(shadow->layer()->visible()); window->Hide(); EXPECT_TRUE(shadow->layer()->visible());