diff --git a/BUILD.gn b/BUILD.gn index 7eecaedb..c6b6735 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -675,12 +675,6 @@ "//third_party/icu/fuzzers", "//third_party/qcms:fuzzers", ] - - # TODO(miu): Remove this dependency once the build configuration in - # chrome/browser/BUILD.gn is migrated to chrome/browser/media/BUILD.gn. - # This dependency here only exists to allow GN to discover the - # fuzzer_test target there. - deps += [ "//chrome/browser/media:cast_remoting_connector_fuzzer" ] } if (enable_nacl) {
diff --git a/DEPS b/DEPS index 4621d3d..60b1c085 100644 --- a/DEPS +++ b/DEPS
@@ -40,7 +40,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '6b65b98996ebc0a511aa46042607a291e6836bed', + 'skia_revision': 'ec045b431211082563a4352ccf2c9d5b3765048e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '2b44441b1b01a809b6f14d44d64db9a52808cba9', + 'pdfium_revision': 'f6f68c75ce54a5865fb19dcb075e7734f1639663', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '3e38417eedda889b4aa978a777b29de401f85b74', + 'catapult_revision': '1e3b1949cdcde84079ef3f0fa3f31610e2d1687d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -262,7 +262,7 @@ Var('chromium_git') + '/external/github.com/google/pywebsocket.git' + '@' + '2d7b73c3acbd0f41dcab487ae5c97c6feae06ce2', 'src/media/cdm/api': - Var('chromium_git') + '/chromium/cdm.git' + '@' + '46eebfa522b06c1f0b52b4233caa56793badf112', + Var('chromium_git') + '/chromium/cdm.git' + '@' + '6e4c388c0117fe408b66fbede91081fb1018c5fe', 'src/third_party/mesa/src': Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + 'ef811c6bd4de74e13e7035ca882cc77f85793fef',
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index 4515045f4..4e3c633 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc
@@ -16,8 +16,8 @@ #include "base/trace_event/trace_event.h" #include "cc/output/compositor_frame.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" #include "ui/gfx/transform.h" #include "ui/gl/gl_bindings.h" @@ -33,7 +33,7 @@ last_committed_layer_tree_frame_sink_id_(0u), last_submitted_layer_tree_frame_sink_id_(0u) { DCHECK(last_egl_context_); - surfaces_->GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_); + surfaces_->GetFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_); CreateNewCompositorFrameSinkSupport(); } @@ -43,7 +43,7 @@ if (child_id_.is_valid()) DestroySurface(); support_.reset(); - surfaces_->GetSurfaceManager()->InvalidateFrameSinkId(frame_sink_id_); + surfaces_->GetFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_); // Reset draw constraints. render_thread_manager_->PostExternalDrawConstraintsToChildCompositorOnRT( @@ -263,7 +263,7 @@ constexpr bool needs_sync_points = true; support_.reset(); support_ = cc::CompositorFrameSinkSupport::Create( - this, surfaces_->GetSurfaceManager(), frame_sink_id_, is_root, + this, surfaces_->GetFrameSinkManager(), frame_sink_id_, is_root, handles_frame_sink_id_invalidation, needs_sync_points); }
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index 22af933..be4af71 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -17,7 +17,6 @@ #include "android_webview/browser/net/aw_web_resource_request.h" #include "android_webview/browser/renderer_host/auto_login_parser.h" #include "android_webview/common/url_constants.h" -#include "base/memory/scoped_vector.h" #include "components/navigation_interception/intercept_navigation_delegate.h" #include "components/safe_browsing_db/safe_browsing_api_handler.h" #include "components/web_restrictions/browser/web_restrictions_resource_throttle.h"
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc index 8855884..eddadbe 100644 --- a/android_webview/browser/surfaces_instance.cc +++ b/android_webview/browser/surfaces_instance.cc
@@ -20,8 +20,8 @@ #include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/display.h" #include "cc/surfaces/display_scheduler.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/transform.h" @@ -54,14 +54,14 @@ // Webview does not own the surface so should not clear it. settings.should_clear_root_render_pass = false; - surface_manager_.reset(new cc::SurfaceManager); + frame_sink_manager_.reset(new cc::FrameSinkManager); local_surface_id_allocator_.reset(new cc::LocalSurfaceIdAllocator()); constexpr bool is_root = true; constexpr bool handles_frame_sink_id_invalidation = true; constexpr bool needs_sync_points = true; support_ = cc::CompositorFrameSinkSupport::Create( - this, surface_manager_.get(), frame_sink_id_, is_root, + this, frame_sink_manager_.get(), frame_sink_id_, is_root, handles_frame_sink_id_invalidation, needs_sync_points); begin_frame_source_.reset(new cc::StubBeginFrameSource); @@ -80,9 +80,9 @@ nullptr /* gpu_memory_buffer_manager */, settings, frame_sink_id_, std::move(output_surface_holder), std::move(scheduler), std::move(texture_mailbox_deleter))); - display_->Initialize(this, surface_manager_.get()); - surface_manager_->RegisterBeginFrameSource(begin_frame_source_.get(), - frame_sink_id_); + display_->Initialize(this, frame_sink_manager_->surface_manager()); + frame_sink_manager_->RegisterBeginFrameSource(begin_frame_source_.get(), + frame_sink_id_); display_->SetVisible(true); @@ -92,7 +92,7 @@ SurfacesInstance::~SurfacesInstance() { DCHECK_EQ(g_surfaces_instance, this); - surface_manager_->UnregisterBeginFrameSource(begin_frame_source_.get()); + frame_sink_manager_->UnregisterBeginFrameSource(begin_frame_source_.get()); g_surfaces_instance = nullptr; DCHECK(child_ids_.empty()); } @@ -106,8 +106,8 @@ return frame_sink_id_allocator_.NextFrameSinkId(); } -cc::SurfaceManager* SurfacesInstance::GetSurfaceManager() { - return surface_manager_.get(); +cc::FrameSinkManager* SurfacesInstance::GetFrameSinkManager() { + return frame_sink_manager_.get(); } void SurfacesInstance::DrawAndSwap(const gfx::Size& viewport,
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h index 1a261e3..cc8c89a 100644 --- a/android_webview/browser/surfaces_instance.h +++ b/android_webview/browser/surfaces_instance.h
@@ -19,8 +19,8 @@ class BeginFrameSource; class CompositorFrameSinkSupport; class Display; +class FrameSinkManager; class LocalSurfaceIdAllocator; -class SurfaceManager; } namespace gfx { @@ -40,7 +40,7 @@ static scoped_refptr<SurfacesInstance> GetOrCreateInstance(); cc::FrameSinkId AllocateFrameSinkId(); - cc::SurfaceManager* GetSurfaceManager(); + cc::FrameSinkManager* GetFrameSinkManager(); void DrawAndSwap(const gfx::Size& viewport, const gfx::Rect& clip, @@ -79,7 +79,7 @@ cc::FrameSinkId frame_sink_id_; - std::unique_ptr<cc::SurfaceManager> surface_manager_; + std::unique_ptr<cc::FrameSinkManager> frame_sink_manager_; std::unique_ptr<cc::BeginFrameSource> begin_frame_source_; std::unique_ptr<cc::Display> display_; std::unique_ptr<cc::LocalSurfaceIdAllocator> local_surface_id_allocator_;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 0c52eabd..6d442ddd 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -1629,8 +1629,7 @@ } // If we are reloading the same url, then set transition type as reload. - if (params.getUrl() != null - && params.getUrl().equals(mWebContents.getUrl()) + if (params.getUrl() != null && params.getUrl().equals(mWebContents.getLastCommittedUrl()) && params.getTransitionType() == PageTransition.LINK) { params.setTransitionType(PageTransition.RELOAD); } @@ -1681,13 +1680,15 @@ } /** - * Get the URL of the current page. + * Get the URL of the current page. This is the visible URL of the {@link WebContents} which may + * be a pending navigation or the last committed URL. For the last committed URL use + * #getLastCommittedUrl(). * * @return The URL of the current page or null if it's empty. */ public String getUrl() { if (isDestroyedOrNoOperation(WARN)) return null; - String url = mWebContents.getUrl(); + String url = mWebContents.getVisibleUrl(); if (url == null || url.trim().isEmpty()) return null; return url; }
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index a71b286..236e85f 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -21,6 +21,7 @@ #include "base/i18n/rtl.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/content/renderer/autofill_agent.h" @@ -320,12 +321,35 @@ // // Format list mirrors: // http://developer.android.com/guide/appendix/media-formats.html + // + // Enum and extension list are parallel arrays and must stay in sync. These + // enum values are written to logs. New enum values can be added, but existing + // enums must never be renumbered or deleted and reused. + enum MediaPlayerContainers { + CONTAINER_3GP = 0, + CONTAINER_TS = 1, + CONTAINER_MID = 2, + CONTAINER_XMF = 3, + CONTAINER_MXMF = 4, + CONTAINER_RTTTL = 5, + CONTAINER_RTX = 6, + CONTAINER_OTA = 7, + CONTAINER_IMY = 8, + MEDIA_PLAYER_CONTAINERS_COUNT, + }; static const char* kMediaPlayerExtensions[] = { - ".3gp", ".ts", ".flac", ".mid", ".xmf", - ".mxmf", ".rtttl", ".rtx", ".ota", ".imy"}; - for (auto* extension : kMediaPlayerExtensions) { - if (base::EndsWith(url.path(), extension, + ".3gp", ".ts", ".mid", ".xmf", ".mxmf", ".rtttl", ".rtx", ".ota", ".imy"}; + static_assert(arraysize(kMediaPlayerExtensions) == + MediaPlayerContainers::MEDIA_PLAYER_CONTAINERS_COUNT, + "Invalid enum or extension change."); + + for (size_t i = 0; i < arraysize(kMediaPlayerExtensions); ++i) { + if (base::EndsWith(url.path(), kMediaPlayerExtensions[i], base::CompareCase::INSENSITIVE_ASCII)) { + UMA_HISTOGRAM_ENUMERATION( + "Media.WebView.UnsupportedContainer", + static_cast<MediaPlayerContainers>(i), + MediaPlayerContainers::MEDIA_PLAYER_CONTAINERS_COUNT); return true; } }
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java index 1363996..b9f781fb 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
@@ -247,7 +247,7 @@ mNextButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE); mPrevButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE); if (!hasFocus) { - mUrlTextView.setText(mWebContents.getUrl()); + mUrlTextView.setText(mWebContents.getVisibleUrl()); } } });
diff --git a/ash/display/display_color_manager_chromeos_unittest.cc b/ash/display/display_color_manager_chromeos_unittest.cc index dc62624..5ae855c5 100644 --- a/ash/display/display_color_manager_chromeos_unittest.cc +++ b/ash/display/display_color_manager_chromeos_unittest.cc
@@ -6,7 +6,6 @@ #include "base/files/file_util.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/pattern.h"
diff --git a/ash/system/night_light/night_light_toggle_button.cc b/ash/system/night_light/night_light_toggle_button.cc index 231d655..74b0d45 100644 --- a/ash/system/night_light/night_light_toggle_button.cc +++ b/ash/system/night_light/night_light_toggle_button.cc
@@ -9,6 +9,7 @@ #include "ash/system/night_light/night_light_controller.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_item_style.h" +#include "ui/accessibility/ax_enums.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/paint_vector_icon.h" @@ -54,6 +55,13 @@ Update(); } +void NightLightToggleButton::Toggle() { + DCHECK(NightLightController::IsFeatureEnabled()); + Shell::Get()->night_light_controller()->Toggle(); + Update(); + NotifyAccessibilityEvent(ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED, true); +} + void NightLightToggleButton::Update() { const bool night_light_enabled = Shell::Get()->night_light_controller()->GetEnabled();
diff --git a/ash/system/night_light/night_light_toggle_button.h b/ash/system/night_light/night_light_toggle_button.h index 7a93c8c..5f9bdcd 100644 --- a/ash/system/night_light/night_light_toggle_button.h +++ b/ash/system/night_light/night_light_toggle_button.h
@@ -16,10 +16,13 @@ explicit NightLightToggleButton(views::ButtonListener* listener); ~NightLightToggleButton() override = default; + // Toggles the status of NightLight. + void Toggle(); + + private: // Updates the icon and its style based on the status of NightLight. void Update(); - private: // views::View: void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
diff --git a/ash/system/tiles/tiles_default_view.cc b/ash/system/tiles/tiles_default_view.cc index 9b5bd50..efa58bd 100644 --- a/ash/system/tiles/tiles_default_view.cc +++ b/ash/system/tiles/tiles_default_view.cc
@@ -126,8 +126,7 @@ } else if (NightLightController::IsFeatureEnabled() && sender == night_light_button_) { Shell::Get()->metrics()->RecordUserMetricsAction(UMA_TRAY_NIGHT_LIGHT); - Shell::Get()->night_light_controller()->Toggle(); - night_light_button_->Update(); + night_light_button_->Toggle(); } else if (sender == lock_button_) { Shell::Get()->metrics()->RecordUserMetricsAction(UMA_TRAY_LOCK_SCREEN); chromeos::DBusThreadManager::Get()
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc index e498c91..2a26022 100644 --- a/ash/wm/lock_state_controller_unittest.cc +++ b/ash/wm/lock_state_controller_unittest.cc
@@ -22,7 +22,6 @@ #include "ash/wm/power_button_controller.h" #include "ash/wm/session_state_animator.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/time/time.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_session_manager_client.h"
diff --git a/base/BUILD.gn b/base/BUILD.gn index a617f10..66297135 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1815,6 +1815,7 @@ # "test/run_all_unittests.cc", "json/json_perftest.cc", + "synchronization/waitable_event_perftest.cc", "threading/thread_perftest.cc", ] deps = [ @@ -2208,6 +2209,7 @@ "template_util_unittest.cc", "test/histogram_tester_unittest.cc", "test/mock_callback_unittest.cc", + "test/scoped_feature_list_unittest.cc", "test/scoped_mock_time_message_loop_task_runner_unittest.cc", "test/scoped_task_environment_unittest.cc", "test/scoped_task_scheduler_unittest.cc",
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc index e9629aa..f5bd0dd 100644 --- a/base/message_loop/message_pump_perftest.cc +++ b/base/message_loop/message_pump_perftest.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/format_macros.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/synchronization/condition_variable.h"
diff --git a/base/synchronization/waitable_event_perftest.cc b/base/synchronization/waitable_event_perftest.cc new file mode 100644 index 0000000..1888077a --- /dev/null +++ b/base/synchronization/waitable_event_perftest.cc
@@ -0,0 +1,178 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/synchronization/waitable_event.h" + +#include <numeric> + +#include "base/threading/simple_thread.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace base { + +namespace { + +class TraceWaitableEvent { + public: + TraceWaitableEvent(size_t samples) + : event_(WaitableEvent::ResetPolicy::AUTOMATIC, + WaitableEvent::InitialState::NOT_SIGNALED), + samples_(samples) { + signal_times_.reserve(samples); + wait_times_.reserve(samples); + } + + ~TraceWaitableEvent() = default; + + void Signal() { + TimeTicks start = TimeTicks::Now(); + event_.Signal(); + signal_times_.push_back(TimeTicks::Now() - start); + } + + void Wait() { + TimeTicks start = TimeTicks::Now(); + event_.Wait(); + wait_times_.push_back(TimeTicks::Now() - start); + } + + bool TimedWaitUntil(const TimeTicks& end_time) { + TimeTicks start = TimeTicks::Now(); + bool signaled = event_.TimedWaitUntil(end_time); + wait_times_.push_back(TimeTicks::Now() - start); + return signaled; + } + + bool IsSignaled() { return event_.IsSignaled(); } + + const std::vector<TimeDelta>& signal_times() const { return signal_times_; } + const std::vector<TimeDelta>& wait_times() const { return wait_times_; } + size_t samples() const { return samples_; } + + private: + WaitableEvent event_; + + std::vector<TimeDelta> signal_times_; + std::vector<TimeDelta> wait_times_; + + const size_t samples_; + + DISALLOW_COPY_AND_ASSIGN(TraceWaitableEvent); +}; + +class SignalerThread : public SimpleThread { + public: + SignalerThread(TraceWaitableEvent* waiter, TraceWaitableEvent* signaler) + : SimpleThread("WaitableEventPerfTest signaler"), + waiter_(waiter), + signaler_(signaler) {} + + ~SignalerThread() override = default; + + void Run() override { + while (!stop_event_.IsSignaled()) { + if (waiter_) + waiter_->Wait(); + if (signaler_) + signaler_->Signal(); + } + } + + // Signals the thread to stop on the next iteration of its loop (which + // will happen immediately if no |waiter_| is present or is signaled. + void RequestStop() { stop_event_.Signal(); } + + private: + WaitableEvent stop_event_{WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED}; + TraceWaitableEvent* waiter_; + TraceWaitableEvent* signaler_; + DISALLOW_COPY_AND_ASSIGN(SignalerThread); +}; + +void PrintPerfWaitableEvent(const TraceWaitableEvent* event, + const std::string& modifier, + const std::string& trace) { + TimeDelta signal_time = std::accumulate( + event->signal_times().begin(), event->signal_times().end(), TimeDelta()); + TimeDelta wait_time = std::accumulate(event->wait_times().begin(), + event->wait_times().end(), TimeDelta()); + perf_test::PrintResult( + "signal_time", modifier, trace, + static_cast<size_t>(signal_time.InNanoseconds()) / event->samples(), + "ns/sample", true); + perf_test::PrintResult( + "wait_time", modifier, trace, + static_cast<size_t>(wait_time.InNanoseconds()) / event->samples(), + "ns/sample", true); +} + +} // namespace + +TEST(WaitableEventPerfTest, SingleThread) { + const size_t kSamples = 1000; + + TraceWaitableEvent event(kSamples); + + for (size_t i = 0; i < kSamples; ++i) { + event.Signal(); + event.Wait(); + } + + PrintPerfWaitableEvent(&event, "", "singlethread-1000-samples"); +} + +TEST(WaitableEventPerfTest, MultipleThreads) { + const size_t kSamples = 1000; + + TraceWaitableEvent waiter(kSamples); + TraceWaitableEvent signaler(kSamples); + + // The other thread will wait and signal on the respective opposite events. + SignalerThread thread(&signaler, &waiter); + thread.Start(); + + for (size_t i = 0; i < kSamples; ++i) { + signaler.Signal(); + waiter.Wait(); + } + + // Signal the stop event and then make sure the signaler event it is + // waiting on is also signaled. + thread.RequestStop(); + signaler.Signal(); + + thread.Join(); + + PrintPerfWaitableEvent(&waiter, "_waiter", "multithread-1000-samples"); + PrintPerfWaitableEvent(&signaler, "_signaler", "multithread-1000-samples"); +} + +TEST(WaitableEventPerfTest, Throughput) { + // Reserve a lot of sample space. + const size_t kCapacity = 500000; + TraceWaitableEvent event(kCapacity); + + SignalerThread thread(nullptr, &event); + thread.Start(); + + TimeTicks end_time = TimeTicks::Now() + TimeDelta::FromSeconds(1); + size_t count = 0; + while (event.TimedWaitUntil(end_time)) { + ++count; + } + + thread.RequestStop(); + thread.Join(); + + perf_test::PrintResult("counts", "", "throughput", count, "signals", true); + PrintPerfWaitableEvent(&event, "", "throughput"); + + // Make sure that allocation didn't happen during the test. + EXPECT_LE(event.signal_times().capacity(), kCapacity); + EXPECT_LE(event.wait_times().capacity(), kCapacity); +} + +} // namespace base
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc index f0f3f4e..22b20b9 100644 --- a/base/test/scoped_feature_list.cc +++ b/base/test/scoped_feature_list.cc
@@ -4,24 +4,79 @@ #include "base/test/scoped_feature_list.h" +#include <algorithm> #include <string> +#include <vector> + +#include "base/stl_util.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" namespace base { namespace test { namespace { -static std::string GetFeatureString( +std::vector<StringPiece> GetFeatureVector( const std::initializer_list<base::Feature>& features) { - std::string output; + std::vector<StringPiece> output; for (const base::Feature& feature : features) { - if (!output.empty()) - output += ","; - output += feature.name; + output.push_back(feature.name); } + return output; } +// Extracts a feature name from a feature state string. For example, given +// the input "*MyLovelyFeature<SomeFieldTrial", returns "MyLovelyFeature". +StringPiece GetFeatureName(StringPiece feature) { + StringPiece feature_name = feature; + + // Remove default info. + if (feature_name.starts_with("*")) + feature_name = feature_name.substr(1); + + // Remove field_trial info. + std::size_t index = feature_name.find("<"); + if (index != std::string::npos) + feature_name = feature_name.substr(0, index); + + return feature_name; +} + +struct Features { + std::vector<StringPiece> enabled_feature_list; + std::vector<StringPiece> disabled_feature_list; +}; + +// Merges previously-specified feature overrides with those passed into one of +// the Init() methods. |features| should be a list of features previously +// overridden to be in the |override_state|. |merged_features| should contain +// the enabled and disabled features passed into the Init() method, plus any +// overrides merged as a result of previous calls to this function. +void OverrideFeatures(const std::string& features, + base::FeatureList::OverrideState override_state, + Features* merged_features) { + std::vector<StringPiece> features_list = + SplitStringPiece(features, ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); + + for (StringPiece feature : features_list) { + StringPiece feature_name = GetFeatureName(feature); + + if (ContainsValue(merged_features->enabled_feature_list, feature_name) || + ContainsValue(merged_features->disabled_feature_list, feature_name)) + continue; + + if (override_state == FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE) { + merged_features->enabled_feature_list.push_back(feature); + } else { + DCHECK_EQ(override_state, + FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE); + merged_features->disabled_feature_list.push_back(feature); + } + } +} + } // namespace ScopedFeatureList::ScopedFeatureList() {} @@ -40,13 +95,6 @@ InitWithFeatureList(std::move(feature_list)); } -void ScopedFeatureList::InitWithFeatures( - const std::initializer_list<base::Feature>& enabled_features, - const std::initializer_list<base::Feature>& disabled_features) { - InitFromCommandLine(GetFeatureString(enabled_features), - GetFeatureString(disabled_features)); -} - void ScopedFeatureList::InitWithFeatureList( std::unique_ptr<FeatureList> feature_list) { DCHECK(!original_feature_list_); @@ -62,12 +110,43 @@ InitWithFeatureList(std::move(feature_list)); } +void ScopedFeatureList::InitWithFeatures( + const std::initializer_list<base::Feature>& enabled_features, + const std::initializer_list<base::Feature>& disabled_features) { + Features merged_features; + merged_features.enabled_feature_list = GetFeatureVector(enabled_features); + merged_features.disabled_feature_list = GetFeatureVector(disabled_features); + + base::FeatureList* feature_list = base::FeatureList::GetInstance(); + + // |current_enabled_features| and |current_disabled_features| must declare out + // of if scope to avoid them out of scope before JoinString calls because + // |merged_features| may contains StringPiece which holding pointer points to + // |current_enabled_features| and |current_disabled_features|. + std::string current_enabled_features; + std::string current_disabled_features; + if (feature_list) { + base::FeatureList::GetInstance()->GetFeatureOverrides( + ¤t_enabled_features, ¤t_disabled_features); + OverrideFeatures(current_enabled_features, + FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE, + &merged_features); + OverrideFeatures(current_disabled_features, + FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE, + &merged_features); + } + + std::string enabled = JoinString(merged_features.enabled_feature_list, ","); + std::string disabled = JoinString(merged_features.disabled_feature_list, ","); + InitFromCommandLine(enabled, disabled); +} + void ScopedFeatureList::InitAndEnableFeature(const base::Feature& feature) { - InitFromCommandLine(feature.name, std::string()); + InitWithFeatures({feature}, {}); } void ScopedFeatureList::InitAndDisableFeature(const base::Feature& feature) { - InitFromCommandLine(std::string(), feature.name); + InitWithFeatures({}, {feature}); } } // namespace test
diff --git a/base/test/scoped_feature_list.h b/base/test/scoped_feature_list.h index 572a263..fb0b39e 100644 --- a/base/test/scoped_feature_list.h +++ b/base/test/scoped_feature_list.h
@@ -32,29 +32,42 @@ ScopedFeatureList(); ~ScopedFeatureList(); + // WARNING: This method will reset any globally configured features to their + // default values, which can hide feature interaction bugs. Please use + // sparingly. https://crbug.com/713390 // Initializes and registers a FeatureList instance with no overrides. void Init(); + // WARNING: This method will reset any globally configured features to their + // default values, which can hide feature interaction bugs. Please use + // sparingly. https://crbug.com/713390 // Initializes and registers the given FeatureList instance. void InitWithFeatureList(std::unique_ptr<FeatureList> feature_list); - // Initializes and registers a FeatureList instance with the given enabled - // and disabled features. - void InitWithFeatures( - const std::initializer_list<base::Feature>& enabled_features, - const std::initializer_list<base::Feature>& disabled_features); - - // Initializes and registers a FeatureList instance with the given + // WARNING: This method will reset any globally configured features to their + // default values, which can hide feature interaction bugs. Please use + // sparingly. https://crbug.com/713390 + // Initializes and registers a FeatureList instance with only the given // enabled and disabled features (comma-separated names). void InitFromCommandLine(const std::string& enable_features, const std::string& disable_features); - // Initializes and registers a FeatureList instance enabling a single - // feature. + // Initializes and registers a FeatureList instance based on present + // FeatureList and overridden with the given enabled and disabled features. + // Any feature overrides already present in the global FeatureList will + // continue to apply, unless they conflict with the overrides passed into this + // method. This is important for testing potentially unexpected feature + // interactions. + void InitWithFeatures( + const std::initializer_list<base::Feature>& enabled_features, + const std::initializer_list<base::Feature>& disabled_features); + + // Initializes and registers a FeatureList instance based on present + // FeatureList and overridden with single enabled feature. void InitAndEnableFeature(const base::Feature& feature); - // Initializes and registers a FeatureList instance disabling a single - // feature. + // Initializes and registers a FeatureList instance based on present + // FeatureList and overridden with single disabled feature. void InitAndDisableFeature(const base::Feature& feature); private:
diff --git a/base/test/scoped_feature_list_unittest.cc b/base/test/scoped_feature_list_unittest.cc new file mode 100644 index 0000000..21d1b4d --- /dev/null +++ b/base/test/scoped_feature_list_unittest.cc
@@ -0,0 +1,188 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_feature_list.h" + +#include <string> +#include "base/metrics/field_trial.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace test { + +namespace { + +const base::Feature kTestFeature1{"TestFeature1", + base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kTestFeature2{"TestFeature2", + base::FEATURE_DISABLED_BY_DEFAULT}; + +void ExpectFeatures(const std::string& enabled_features, + const std::string& disabled_features) { + base::FeatureList* list = base::FeatureList::GetInstance(); + std::string actual_enabled_features; + std::string actual_disabled_features; + + list->GetFeatureOverrides(&actual_enabled_features, + &actual_disabled_features); + + EXPECT_EQ(enabled_features, actual_enabled_features); + EXPECT_EQ(disabled_features, actual_disabled_features); +} + +} // namespace + +class ScopedFeatureListTest : public testing::Test { + public: + ScopedFeatureListTest() { + // Clear default feature list. + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine(std::string(), std::string()); + original_feature_list_ = base::FeatureList::ClearInstanceForTesting(); + base::FeatureList::SetInstance(std::move(feature_list)); + } + + ~ScopedFeatureListTest() override { + // Restore feature list. + if (original_feature_list_) { + base::FeatureList::ClearInstanceForTesting(); + base::FeatureList::RestoreInstanceForTesting( + std::move(original_feature_list_)); + } + } + + private: + // Save the present FeatureList and restore it after test finish. + std::unique_ptr<FeatureList> original_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(ScopedFeatureListTest); +}; + +TEST_F(ScopedFeatureListTest, BasicScoped) { + ExpectFeatures(std::string(), std::string()); + EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1)); + { + test::ScopedFeatureList feature_list1; + feature_list1.InitFromCommandLine("TestFeature1", std::string()); + ExpectFeatures("TestFeature1", std::string()); + EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); + } + ExpectFeatures(std::string(), std::string()); + EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1)); +} + +TEST_F(ScopedFeatureListTest, EnableFeatureOverrideDisable) { + test::ScopedFeatureList feature_list1; + feature_list1.InitWithFeatures({}, {kTestFeature1}); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({kTestFeature1}, {}); + ExpectFeatures("TestFeature1", std::string()); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideNotMakeDuplicate) { + test::ScopedFeatureList feature_list1; + feature_list1.InitWithFeatures({}, {kTestFeature1}); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({}, {kTestFeature1}); + ExpectFeatures(std::string(), "TestFeature1"); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault) { + test::ScopedFeatureList feature_list1; + feature_list1.InitFromCommandLine("*TestFeature1", std::string()); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({kTestFeature1}, {}); + ExpectFeatures("TestFeature1", std::string()); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault2) { + test::ScopedFeatureList feature_list1; + feature_list1.InitFromCommandLine("*TestFeature1", std::string()); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({}, {kTestFeature1}); + ExpectFeatures(std::string(), "TestFeature1"); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithEnabledFieldTried) { + test::ScopedFeatureList feature_list1; + + std::unique_ptr<FeatureList> feature_list(new FeatureList); + FieldTrialList field_trial_list(nullptr); + FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A"); + feature_list->RegisterFieldTrialOverride( + kTestFeature1.name, FeatureList::OVERRIDE_ENABLE_FEATURE, trial); + feature_list1.InitWithFeatureList(std::move(feature_list)); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({kTestFeature1}, {}); + ExpectFeatures("TestFeature1", std::string()); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDisabledFieldTried) { + test::ScopedFeatureList feature_list1; + + std::unique_ptr<FeatureList> feature_list(new FeatureList); + FieldTrialList field_trial_list(nullptr); + FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A"); + feature_list->RegisterFieldTrialOverride( + kTestFeature1.name, FeatureList::OVERRIDE_DISABLE_FEATURE, trial); + feature_list1.InitWithFeatureList(std::move(feature_list)); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({kTestFeature1}, {}); + ExpectFeatures("TestFeature1", std::string()); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature) { + test::ScopedFeatureList feature_list1; + feature_list1.InitWithFeatures({}, {kTestFeature1}); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({}, {kTestFeature2}); + EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1)); + EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2)); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature2) { + test::ScopedFeatureList feature_list1; + feature_list1.InitWithFeatures({}, {kTestFeature1}); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({kTestFeature2}, {}); + ExpectFeatures("TestFeature2", "TestFeature1"); + } +} + +TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingDefaultFeature) { + test::ScopedFeatureList feature_list1; + feature_list1.InitFromCommandLine("*TestFeature1", std::string()); + + { + test::ScopedFeatureList feature_list2; + feature_list2.InitWithFeatures({}, {kTestFeature2}); + ExpectFeatures("*TestFeature1", "TestFeature2"); + } +} + +} // namespace test +} // namespace base
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc index 39f192c..92f24675 100644 --- a/base/threading/thread_perftest.cc +++ b/base/threading/thread_perftest.cc
@@ -227,8 +227,8 @@ // using WaitableEvents. We only test four threads (worst-case), but we // might want to craft a way to test the best-case (where the thread doesn't // end up blocking because the event is already signalled). -typedef EventPerfTest<base::WaitableEvent> WaitableEventPerfTest; -TEST_F(WaitableEventPerfTest, EventPingPong) { +typedef EventPerfTest<base::WaitableEvent> WaitableEventThreadPerfTest; +TEST_F(WaitableEventThreadPerfTest, EventPingPong) { RunPingPongTest("4_WaitableEvent_Threads", 4); }
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h index c0c2f81..a6b7d6d9 100644 --- a/base/trace_event/process_memory_dump.h +++ b/base/trace_event/process_memory_dump.h
@@ -15,7 +15,6 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/trace_event/heap_profiler_serialization_state.h" #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/memory_allocator_dump_guid.h"
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h index b5ebc4f6..9e7db7d 100644 --- a/base/trace_event/trace_log.h +++ b/base/trace_event/trace_log.h
@@ -16,7 +16,6 @@ #include "base/atomicops.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/trace_config.h" #include "base/trace_event/trace_event_impl.h"
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py index cc376d18..1e5056b 100644 --- a/build/android/pylib/local/device/local_device_environment.py +++ b/build/android/pylib/local/device/local_device_environment.py
@@ -138,7 +138,7 @@ @handle_shard_failures_with(on_failure=self.BlacklistDevice) def prepare_device(d): - d.WaitUntilFullyBooted(timeout=10) + d.WaitUntilFullyBooted() if self._enable_device_cache: cache_path = _DeviceCachePath(d)
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index ea261d1e..8b0d79f 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -863,11 +863,11 @@ "surfaces/direct_layer_tree_frame_sink_unittest.cc", "surfaces/display_scheduler_unittest.cc", "surfaces/display_unittest.cc", + "surfaces/frame_sink_manager_unittest.cc", "surfaces/referenced_surface_tracker_unittest.cc", "surfaces/surface_aggregator_unittest.cc", "surfaces/surface_hittest_unittest.cc", "surfaces/surface_manager_ref_unittest.cc", - "surfaces/surface_manager_unittest.cc", "surfaces/surface_sequence_generator_unittest.cc", "surfaces/surface_synchronization_unittest.cc", "surfaces/surface_unittest.cc",
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 0050c8e6..f744ccf 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -223,7 +223,6 @@ resource_provider->CopyToResource( resources_.back()->id(), static_cast<const uint8_t*>(pixmap.addr()), internal_content_bounds_); - resource_provider->GenerateSyncTokenForResource(resources_.back()->id()); } }
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index a81d66ac..4835c97d 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -137,8 +137,6 @@ resource_provider->CopyToResource(texture_copy_->id(), pixels, texture_mailbox_.size_in_pixels()); - resource_provider->GenerateSyncTokenForResource(texture_copy_->id()); - valid_texture_copy_ = true; } }
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 33cb6a3..c1382b3 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc
@@ -137,7 +137,6 @@ external_resources.mailboxes[i].is_overlay_candidate())); resource_ids.push_back(resource_id); } - resource_provider->GenerateSyncTokenForResources(resource_ids); return true; }
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index 57de616..1c53186 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -25,6 +25,10 @@ "paint_image.h", "paint_op_buffer.cc", "paint_op_buffer.h", + "paint_op_reader.cc", + "paint_op_reader.h", + "paint_op_writer.cc", + "paint_op_writer.h", "paint_record.cc", "paint_record.h", "paint_recorder.cc",
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h index 6954892d..940751c 100644 --- a/cc/paint/paint_flags.h +++ b/cc/paint/paint_flags.h
@@ -224,6 +224,9 @@ bool SupportsFoldingAlpha() const; private: + friend class PaintOpReader; + friend class PaintOpWriter; + friend const SkPaint& ToSkPaint(const PaintFlags& flags); friend const SkPaint* ToSkPaint(const PaintFlags* flags);
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 981622d..907f4e9 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -6,6 +6,8 @@ #include "base/containers/stack_container.h" #include "cc/paint/display_item_list.h" +#include "cc/paint/paint_op_reader.h" +#include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -136,6 +138,24 @@ static_assert(kNumOpTypes == TYPES(M), "Missing op in list"); #undef M +using SerializeFunction = size_t (*)(const PaintOp* op, + void* memory, + size_t size, + const PaintOp::SerializeOptions& options); +#define M(T) &T::Serialize, +static const SerializeFunction g_serialize_functions[kNumOpTypes] = {TYPES(M)}; +#undef M + +using DeserializeFunction = PaintOp* (*)(const void* input, + size_t input_size, + void* output, + size_t output_size); + +#define M(T) &T::Deserialize, +static const DeserializeFunction g_deserialize_functions[kNumOpTypes] = { + TYPES(M)}; +#undef M + using RasterFunction = void (*)(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); @@ -187,6 +207,7 @@ #undef TYPES SkRect PaintOp::kUnsetRect = {SK_ScalarInfinity, 0, 0, 0}; +const size_t PaintOp::kMaxSkip; std::string PaintOpTypeToString(PaintOpType type) { switch (type) { @@ -254,6 +275,785 @@ return "UNKNOWN"; } +template <typename T> +size_t SimpleSerialize(const PaintOp* op, void* memory, size_t size) { + if (sizeof(T) > size) + return 0; + memcpy(memory, op, sizeof(T)); + return sizeof(T); +} + +size_t AnnotateOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const AnnotateOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->annotation_type); + helper.Write(op->rect); + helper.Write(op->data); + return helper.size(); +} + +size_t ClipPathOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const ClipPathOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->path); + helper.Write(op->op); + helper.Write(op->antialias); + return helper.size(); +} + +size_t ClipRectOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ClipRectOp>(op, memory, size); +} + +size_t ClipRRectOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ClipRRectOp>(op, memory, size); +} + +size_t ConcatOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ConcatOp>(op, memory, size); +} + +size_t DrawArcOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawArcOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->oval); + helper.Write(op->start_angle); + helper.Write(op->sweep_angle); + helper.Write(op->use_center); + return helper.size(); +} + +size_t DrawCircleOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawCircleOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->cx); + helper.Write(op->cy); + helper.Write(op->radius); + return helper.size(); +} + +size_t DrawColorOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<DrawColorOp>(op, memory, size); +} + +size_t DrawDRRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawDRRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->outer); + helper.Write(op->inner); + return helper.size(); +} + +size_t DrawImageOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawImageOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->image, options.decode_cache); + helper.Write(op->left); + helper.Write(op->top); + return helper.size(); +} + +size_t DrawImageRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawImageRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->image, options.decode_cache); + helper.Write(op->src); + helper.Write(op->dst); + helper.Write(op->constraint); + return helper.size(); +} + +size_t DrawIRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawIRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->rect); + return helper.size(); +} + +size_t DrawLineOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawLineOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->x0); + helper.Write(op->y0); + helper.Write(op->x1); + helper.Write(op->y1); + return helper.size(); +} + +size_t DrawOvalOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawOvalOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->oval); + return helper.size(); +} + +size_t DrawPathOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawPathOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->path); + return helper.size(); +} + +size_t DrawPosTextOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawPosTextOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->count); + helper.Write(op->bytes); + helper.WriteArray(op->count, op->GetArray()); + helper.WriteData(op->bytes, op->GetData()); + return helper.size(); +} + +size_t DrawRecordOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + // TODO(enne): these must be flattened. Serializing this will not do + // anything. + NOTREACHED(); + return 0u; +} + +size_t DrawRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->rect); + return helper.size(); +} + +size_t DrawRRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawRRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->rrect); + return helper.size(); +} + +size_t DrawTextOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawTextOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->x); + helper.Write(op->y); + helper.Write(op->bytes); + helper.WriteData(op->bytes, op->GetData()); + return helper.size(); +} + +size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawTextBlobOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->x); + helper.Write(op->y); + helper.Write(op->blob); + return helper.size(); +} + +size_t NoopOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<NoopOp>(op, memory, size); +} + +size_t RestoreOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<RestoreOp>(op, memory, size); +} + +size_t RotateOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<RotateOp>(op, memory, size); +} + +size_t SaveOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<SaveOp>(op, memory, size); +} + +size_t SaveLayerOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const SaveLayerOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->bounds); + return helper.size(); +} + +size_t SaveLayerAlphaOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<SaveLayerAlphaOp>(op, memory, size); +} + +size_t ScaleOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ScaleOp>(op, memory, size); +} + +size_t SetMatrixOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<SetMatrixOp>(op, memory, size); +} + +size_t TranslateOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<TranslateOp>(op, memory, size); +} + +template <typename T> +void UpdateTypeAndSkip(T* op) { + op->type = static_cast<uint8_t>(T::kType); + op->skip = MathUtil::UncheckedRoundUp(sizeof(T), PaintOpBuffer::PaintOpAlign); +} + +template <typename T> +PaintOp* SimpleDeserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + if (input_size < sizeof(T)) + return nullptr; + memcpy(output, input, sizeof(T)); + + T* op = reinterpret_cast<T*>(output); + // Type and skip were already read once, so could have been changed. + // Don't trust them and clobber them with something valid. + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* AnnotateOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(AnnotateOp)); + AnnotateOp* op = new (output) AnnotateOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->annotation_type); + helper.Read(&op->rect); + helper.Read(&op->data); + if (!helper.valid()) { + op->~AnnotateOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* ClipPathOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(ClipPathOp)); + ClipPathOp* op = new (output) ClipPathOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->path); + helper.Read(&op->op); + helper.Read(&op->antialias); + if (!helper.valid()) { + op->~ClipPathOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* ClipRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ClipRectOp>(input, input_size, output, output_size); +} + +PaintOp* ClipRRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ClipRRectOp>(input, input_size, output, output_size); +} + +PaintOp* ConcatOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ConcatOp>(input, input_size, output, output_size); +} + +PaintOp* DrawArcOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawArcOp)); + DrawArcOp* op = new (output) DrawArcOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->oval); + helper.Read(&op->start_angle); + helper.Read(&op->sweep_angle); + helper.Read(&op->use_center); + if (!helper.valid()) { + op->~DrawArcOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawCircleOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawCircleOp)); + DrawCircleOp* op = new (output) DrawCircleOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->cx); + helper.Read(&op->cy); + helper.Read(&op->radius); + if (!helper.valid()) { + op->~DrawCircleOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawColorOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<DrawColorOp>(input, input_size, output, output_size); +} + +PaintOp* DrawDRRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawDRRectOp)); + DrawDRRectOp* op = new (output) DrawDRRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->outer); + helper.Read(&op->inner); + if (!helper.valid()) { + op->~DrawDRRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawImageOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawImageOp)); + DrawImageOp* op = new (output) DrawImageOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->image); + helper.Read(&op->left); + helper.Read(&op->top); + if (!helper.valid()) { + op->~DrawImageOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawImageRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawImageRectOp)); + DrawImageRectOp* op = new (output) DrawImageRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->image); + helper.Read(&op->src); + helper.Read(&op->dst); + helper.Read(&op->constraint); + if (!helper.valid()) { + op->~DrawImageRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawIRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawIRectOp)); + DrawIRectOp* op = new (output) DrawIRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->rect); + if (!helper.valid()) { + op->~DrawIRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawLineOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawLineOp)); + DrawLineOp* op = new (output) DrawLineOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->x0); + helper.Read(&op->y0); + helper.Read(&op->x1); + helper.Read(&op->y1); + if (!helper.valid()) { + op->~DrawLineOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawOvalOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawOvalOp)); + DrawOvalOp* op = new (output) DrawOvalOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->oval); + if (!helper.valid()) { + op->~DrawOvalOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawPathOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawPathOp)); + DrawPathOp* op = new (output) DrawPathOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->path); + if (!helper.valid()) { + op->~DrawPathOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawPosTextOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + // TODO(enne): This is a bit of a weird condition, but to avoid the code + // complexity of every Deserialize function being able to (re)allocate + // an aligned buffer of the right size, this function asserts that it + // will have enough size for the extra data. It's guaranteed that any extra + // memory is at most |input_size| so that plus the op size is an upper bound. + // The caller has to awkwardly do this allocation though, sorry. + CHECK_GE(output_size, sizeof(DrawPosTextOp) + input_size); + DrawPosTextOp* op = new (output) DrawPosTextOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->count); + helper.Read(&op->bytes); + if (helper.valid()) { + helper.ReadArray(op->count, op->GetArray()); + helper.ReadData(op->bytes, op->GetData()); + } + if (!helper.valid()) { + op->~DrawPosTextOp(); + return nullptr; + } + + op->type = static_cast<uint8_t>(PaintOpType::DrawPosText); + op->skip = MathUtil::UncheckedRoundUp( + sizeof(DrawPosTextOp) + op->bytes + sizeof(SkPoint) * op->count, + PaintOpBuffer::PaintOpAlign); + + return op; +} + +PaintOp* DrawRecordOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + // TODO(enne): these must be flattened and not sent directly. + // TODO(enne): could also consider caching these service side. + NOTREACHED(); + return nullptr; +} + +PaintOp* DrawRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawRectOp)); + DrawRectOp* op = new (output) DrawRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->rect); + if (!helper.valid()) { + op->~DrawRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawRRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawRRectOp)); + DrawRRectOp* op = new (output) DrawRRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->rrect); + if (!helper.valid()) { + op->~DrawRRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawTextOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawTextOp) + input_size); + DrawTextOp* op = new (output) DrawTextOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->x); + helper.Read(&op->y); + helper.Read(&op->bytes); + if (helper.valid()) + helper.ReadData(op->bytes, op->GetData()); + if (!helper.valid()) { + op->~DrawTextOp(); + return nullptr; + } + + op->type = static_cast<uint8_t>(PaintOpType::DrawText); + op->skip = MathUtil::UncheckedRoundUp(sizeof(DrawTextOp) + op->bytes, + PaintOpBuffer::PaintOpAlign); + return op; +} + +PaintOp* DrawTextBlobOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawTextBlobOp)); + DrawTextBlobOp* op = new (output) DrawTextBlobOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->x); + helper.Read(&op->y); + helper.Read(&op->blob); + if (!helper.valid()) { + op->~DrawTextBlobOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* NoopOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<NoopOp>(input, input_size, output, output_size); +} + +PaintOp* RestoreOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<RestoreOp>(input, input_size, output, output_size); +} + +PaintOp* RotateOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<RotateOp>(input, input_size, output, output_size); +} + +PaintOp* SaveOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<SaveOp>(input, input_size, output, output_size); +} + +PaintOp* SaveLayerOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(SaveLayerOp)); + SaveLayerOp* op = new (output) SaveLayerOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->bounds); + if (!helper.valid()) { + op->~SaveLayerOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* SaveLayerAlphaOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<SaveLayerAlphaOp>(input, input_size, output, + output_size); +} + +PaintOp* ScaleOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ScaleOp>(input, input_size, output, output_size); +} + +PaintOp* SetMatrixOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<SetMatrixOp>(input, input_size, output, output_size); +} + +PaintOp* TranslateOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<TranslateOp>(input, input_size, output, output_size); +} + void AnnotateOp::Raster(const PaintOp* base_op, SkCanvas* canvas, const SkMatrix& original_ctm) { @@ -516,6 +1316,59 @@ g_raster_alpha_functions[type](this, canvas, bounds, alpha); } +size_t PaintOp::Serialize(void* memory, + size_t size, + const SerializeOptions& options) const { + // Need at least enough room for a skip/type header. + if (size < 4) + return 0u; + + DCHECK_EQ(0u, + reinterpret_cast<uintptr_t>(memory) % PaintOpBuffer::PaintOpAlign); + + size_t written = g_serialize_functions[type](this, memory, size, options); + DCHECK_LE(written, size); + if (written < 4) + return 0u; + + size_t aligned_written = + MathUtil::UncheckedRoundUp(written, PaintOpBuffer::PaintOpAlign); + if (aligned_written >= kMaxSkip) + return 0u; + if (aligned_written > size) + return 0u; + + // Update skip and type now that the size is known. + uint32_t skip = static_cast<uint32_t>(aligned_written); + static_cast<uint32_t*>(memory)[0] = type | skip << 8; + return skip; +} + +PaintOp* PaintOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + // TODO(enne): assert that output_size is big enough. + const PaintOp* serialized = reinterpret_cast<const PaintOp*>(input); + uint32_t skip = serialized->skip; + if (input_size < skip) + return nullptr; + if (skip % PaintOpBuffer::PaintOpAlign != 0) + return nullptr; + uint8_t type = serialized->type; + if (type > static_cast<uint8_t>(PaintOpType::LastPaintOpType)) + return nullptr; + + return g_deserialize_functions[serialized->type](input, skip, output, + output_size); +} + +void PaintOp::DestroyThis() { + auto func = g_destructor_functions[type]; + if (func) + func(this); +} + int ClipPathOp::CountSlowPaths() const { return antialias && !path.isConvex() ? 1 : 0; } @@ -563,6 +1416,8 @@ return record->HasNonAAPaint(); } +AnnotateOp::AnnotateOp() = default; + AnnotateOp::AnnotateOp(PaintCanvas::AnnotationType annotation_type, const SkRect& rect, sk_sp<SkData> data) @@ -587,6 +1442,8 @@ DrawImageOp::~DrawImageOp() = default; +DrawImageRectOp::DrawImageRectOp() = default; + DrawImageRectOp::DrawImageRectOp(const PaintImage& image, const SkRect& src, const SkRect& dst, @@ -604,6 +1461,8 @@ DrawImageRectOp::~DrawImageRectOp() = default; +DrawPosTextOp::DrawPosTextOp() = default; + DrawPosTextOp::DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags) @@ -611,6 +1470,8 @@ DrawPosTextOp::~DrawPosTextOp() = default; +DrawRecordOp::DrawRecordOp() = default; + DrawRecordOp::DrawRecordOp(sk_sp<const PaintRecord> record) : record(std::move(record)) {} @@ -624,6 +1485,8 @@ return record->HasDiscardableImages(); } +DrawTextBlobOp::DrawTextBlobOp() = default; + DrawTextBlobOp::DrawTextBlobOp(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, @@ -658,11 +1521,8 @@ } void PaintOpBuffer::Reset() { - for (auto* op : Iterator(this)) { - auto func = g_destructor_functions[op->type]; - if (func) - func(op); - } + for (auto* op : Iterator(this)) + op->DestroyThis(); // Leave data_ allocated, reserved_ unchanged. used_ = 0; @@ -793,7 +1653,7 @@ // Compute a skip such that all ops in the buffer are aligned to the // maximum required alignment of all ops. size_t skip = MathUtil::UncheckedRoundUp(sizeof_op + bytes, PaintOpAlign); - DCHECK_LT(skip, static_cast<size_t>(1) << 24); + DCHECK_LT(skip, PaintOp::kMaxSkip); if (used_ + skip > reserved_) { // Start reserved_ at kInitialBufferSize and then double. // ShrinkToFit can make this smaller afterwards.
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index d3cba68a2..fbbb65d6c 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -27,6 +27,8 @@ namespace cc { +class ImageDecodeCache; + class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix { public: explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) { @@ -39,8 +41,18 @@ explicit ThreadsafePath(const SkPath& path) : SkPath(path) { updateBoundsCache(); } + ThreadsafePath() { updateBoundsCache(); } }; +// See PaintOp::Serialize/Deserialize for comments. Derived Serialize types +// don't write the 4 byte type/skip header because they don't know how much +// data they will need to write. PaintOp::Serialize itself must update it. +#define HAS_SERIALIZATION_FUNCTIONS() \ + static size_t Serialize(const PaintOp* op, void* memory, size_t size, \ + const SerializeOptions& options); \ + static PaintOp* Deserialize(const void* input, size_t input_size, \ + void* output, size_t output_size); + enum class PaintOpType : uint8_t { Annotate, ClipPath, @@ -75,9 +87,10 @@ LastPaintOpType = Translate, }; -std::string PaintOpTypeToString(PaintOpType type); +CC_PAINT_EXPORT std::string PaintOpTypeToString(PaintOpType type); -struct CC_PAINT_EXPORT PaintOp { +class CC_PAINT_EXPORT PaintOp { + public: uint32_t type : 8; uint32_t skip : 24; @@ -90,6 +103,28 @@ void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const; bool IsDrawOp() const; + struct SerializeOptions { + ImageDecodeCache* decode_cache = nullptr; + }; + + // Subclasses should provide a static Serialize() method called from here. + // If the op can be serialized to |memory| in no more than |size| bytes, + // then return the number of bytes written. If it won't fit, return 0. + size_t Serialize(void* memory, + size_t size, + const SerializeOptions& options) const; + + // Deserializes a PaintOp of this type from a given buffer |input| of + // at most |input_size| bytes. Returns null on any errors. + // The PaintOp is deserialized into the |output| buffer and returned + // if valid. nullptr is returned if the deserialization fails. + // |output_size| must be at least LargestPaintOp + serialized->skip, + // to fit all ops. The caller is responsible for destroying these ops. + static PaintOp* Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size); + // Only valid for draw ops. void RasterWithAlpha(SkCanvas* canvas, const SkRect& bounds, @@ -107,14 +142,20 @@ // and display lists. This doesn't count other objects like paths or blobs. size_t AdditionalBytesUsed() const { return 0; } + // Run the destructor for the derived op type. Ops are usually contained in + // memory buffers and so don't have their destructors run automatically. + void DestroyThis(); + static constexpr bool kIsDrawOp = false; static constexpr bool kHasPaintFlags = false; + // Since skip and type fit in a uint32_t, this is the max size of skip. + static constexpr size_t kMaxSkip = static_cast<size_t>(1 << 24); static SkRect kUnsetRect; }; -struct CC_PAINT_EXPORT PaintOpWithFlags : PaintOp { +class CC_PAINT_EXPORT PaintOpWithFlags : public PaintOp { + public: static constexpr bool kHasPaintFlags = true; - explicit PaintOpWithFlags(const PaintFlags& flags) : flags(flags) {} int CountSlowPathsFromFlags() const { return flags.getPathEffect() ? 1 : 0; } @@ -135,9 +176,13 @@ // a const PaintOpWithFlags* parameter so that it can be used as a function // pointer. PaintFlags flags; + + protected: + PaintOpWithFlags() = default; }; -struct CC_PAINT_EXPORT PaintOpWithData : PaintOpWithFlags { +class CC_PAINT_EXPORT PaintOpWithData : public PaintOpWithFlags { + public: // Having data is just a helper for ops that have a varying amount of data and // want a way to store that inline. This is for ops that pass in a // void* and a length. The void* data is assumed to not have any alignment @@ -150,6 +195,8 @@ size_t bytes; protected: + PaintOpWithData() = default; + // For some derived object T, return the internally stored data. // This needs the fully derived type to know how much to offset // from the start of the top to the data. @@ -173,13 +220,18 @@ } }; -struct CC_PAINT_EXPORT PaintOpWithArrayBase : PaintOpWithFlags { +class CC_PAINT_EXPORT PaintOpWithArrayBase : public PaintOpWithFlags { + public: explicit PaintOpWithArrayBase(const PaintFlags& flags) : PaintOpWithFlags(flags) {} + + protected: + PaintOpWithArrayBase() = default; }; template <typename M> -struct CC_PAINT_EXPORT PaintOpWithArray : PaintOpWithArrayBase { +class CC_PAINT_EXPORT PaintOpWithArray : public PaintOpWithArrayBase { + public: // Paint op that has a M[count] and a char[bytes]. // Array data is stored first so that it can be aligned with T's alignment // with the arbitrary unaligned char data after it. @@ -192,6 +244,8 @@ size_t count; protected: + PaintOpWithArray() = default; + template <typename T> const void* GetDataForThis(const T* op) const { static_assert(std::is_convertible<T, PaintOpWithArrayBase>::value, @@ -233,7 +287,8 @@ } }; -struct CC_PAINT_EXPORT AnnotateOp final : PaintOp { +class CC_PAINT_EXPORT AnnotateOp final : public PaintOp { + public: enum class AnnotationType { URL, LinkToDestination, @@ -248,13 +303,18 @@ static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); PaintCanvas::AnnotationType annotation_type; SkRect rect; sk_sp<SkData> data; + + private: + AnnotateOp(); }; -struct CC_PAINT_EXPORT ClipPathOp final : PaintOp { +class CC_PAINT_EXPORT ClipPathOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::ClipPath; ClipPathOp(SkPath path, SkClipOp op, bool antialias) : path(path), op(op), antialias(antialias) {} @@ -263,26 +323,36 @@ const SkMatrix& original_ctm); int CountSlowPaths() const; bool HasNonAAPaint() const { return !antialias; } + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafePath path; SkClipOp op; bool antialias; + + private: + ClipPathOp() = default; }; -struct CC_PAINT_EXPORT ClipRectOp final : PaintOp { +class CC_PAINT_EXPORT ClipRectOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::ClipRect; ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias) : rect(rect), op(op), antialias(antialias) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect rect; SkClipOp op; bool antialias; + + private: + ClipRectOp() = default; }; -struct CC_PAINT_EXPORT ClipRRectOp final : PaintOp { +class CC_PAINT_EXPORT ClipRRectOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::ClipRRect; ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias) : rrect(rrect), op(op), antialias(antialias) {} @@ -290,23 +360,33 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasNonAAPaint() const { return !antialias; } + HAS_SERIALIZATION_FUNCTIONS(); SkRRect rrect; SkClipOp op; bool antialias; + + private: + ClipRRectOp() = default; }; -struct CC_PAINT_EXPORT ConcatOp final : PaintOp { +class CC_PAINT_EXPORT ConcatOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Concat; explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; + + private: + ConcatOp() = default; }; -struct CC_PAINT_EXPORT DrawArcOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawArcOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawArc; static constexpr bool kIsDrawOp = true; DrawArcOp(const SkRect& oval, @@ -329,14 +409,19 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect oval; SkScalar start_angle; SkScalar sweep_angle; bool use_center; + + private: + DrawArcOp() = default; }; -struct CC_PAINT_EXPORT DrawCircleOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawCircleOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawCircle; static constexpr bool kIsDrawOp = true; DrawCircleOp(SkScalar cx, @@ -354,25 +439,35 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar cx; SkScalar cy; SkScalar radius; + + private: + DrawCircleOp() = default; }; -struct CC_PAINT_EXPORT DrawColorOp final : PaintOp { +class CC_PAINT_EXPORT DrawColorOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::DrawColor; static constexpr bool kIsDrawOp = true; DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkColor color; SkBlendMode mode; + + private: + DrawColorOp() = default; }; -struct CC_PAINT_EXPORT DrawDRRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawDRRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawDRRect; static constexpr bool kIsDrawOp = true; DrawDRRectOp(const SkRRect& outer, @@ -389,12 +484,17 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRRect outer; SkRRect inner; + + private: + DrawDRRectOp() = default; }; -struct CC_PAINT_EXPORT DrawImageOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawImageOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawImage; static constexpr bool kIsDrawOp = true; DrawImageOp(const PaintImage& image, @@ -414,13 +514,18 @@ const SkMatrix& original_ctm); bool HasDiscardableImages() const; bool HasNonAAPaint() const { return false; } + HAS_SERIALIZATION_FUNCTIONS(); PaintImage image; SkScalar left; SkScalar top; + + private: + DrawImageOp() = default; }; -struct CC_PAINT_EXPORT DrawImageRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawImageRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawImageRect; static constexpr bool kIsDrawOp = true; DrawImageRectOp(const PaintImage& image, @@ -440,14 +545,19 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasDiscardableImages() const; + HAS_SERIALIZATION_FUNCTIONS(); PaintImage image; SkRect src; SkRect dst; PaintCanvas::SrcRectConstraint constraint; + + private: + DrawImageRectOp(); }; -struct CC_PAINT_EXPORT DrawIRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawIRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawIRect; static constexpr bool kIsDrawOp = true; DrawIRectOp(const SkIRect& rect, const PaintFlags& flags) @@ -463,11 +573,16 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasNonAAPaint() const { return false; } + HAS_SERIALIZATION_FUNCTIONS(); SkIRect rect; + + private: + DrawIRectOp() = default; }; -struct CC_PAINT_EXPORT DrawLineOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawLineOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawLine; static constexpr bool kIsDrawOp = true; DrawLineOp(SkScalar x0, @@ -486,6 +601,7 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); int CountSlowPaths() const; @@ -493,9 +609,13 @@ SkScalar y0; SkScalar x1; SkScalar y1; + + private: + DrawLineOp() = default; }; -struct CC_PAINT_EXPORT DrawOvalOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawOvalOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawOval; static constexpr bool kIsDrawOp = true; DrawOvalOp(const SkRect& oval, const PaintFlags& flags) @@ -510,11 +630,16 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect oval; + + private: + DrawOvalOp() = default; }; -struct CC_PAINT_EXPORT DrawPathOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawPathOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawPath; static constexpr bool kIsDrawOp = true; DrawPathOp(const SkPath& path, const PaintFlags& flags) @@ -530,11 +655,16 @@ SkCanvas* canvas, const SkMatrix& original_ctm); int CountSlowPaths() const; + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafePath path; + + private: + DrawPathOp() = default; }; -struct CC_PAINT_EXPORT DrawPosTextOp final : PaintOpWithArray<SkPoint> { +class CC_PAINT_EXPORT DrawPosTextOp final : public PaintOpWithArray<SkPoint> { + public: static constexpr PaintOpType kType = PaintOpType::DrawPosText; static constexpr bool kIsDrawOp = true; DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags); @@ -549,14 +679,19 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); const void* GetData() const { return GetDataForThis(this); } void* GetData() { return GetDataForThis(this); } const SkPoint* GetArray() const { return GetArrayForThis(this); } SkPoint* GetArray() { return GetArrayForThis(this); } + + private: + DrawPosTextOp(); }; -struct CC_PAINT_EXPORT DrawRecordOp final : PaintOp { +class CC_PAINT_EXPORT DrawRecordOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::DrawRecord; static constexpr bool kIsDrawOp = true; explicit DrawRecordOp(sk_sp<const PaintRecord> record); @@ -568,11 +703,16 @@ bool HasDiscardableImages() const; int CountSlowPaths() const; bool HasNonAAPaint() const; + HAS_SERIALIZATION_FUNCTIONS(); sk_sp<const PaintRecord> record; + + private: + DrawRecordOp(); }; -struct CC_PAINT_EXPORT DrawRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawRect; static constexpr bool kIsDrawOp = true; DrawRectOp(const SkRect& rect, const PaintFlags& flags) @@ -587,11 +727,16 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect rect; + + private: + DrawRectOp() = default; }; -struct CC_PAINT_EXPORT DrawRRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawRRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawRRect; static constexpr bool kIsDrawOp = true; DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags) @@ -606,11 +751,16 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRRect rrect; + + private: + DrawRRectOp() = default; }; -struct CC_PAINT_EXPORT DrawTextOp final : PaintOpWithData { +class CC_PAINT_EXPORT DrawTextOp final : public PaintOpWithData { + public: static constexpr PaintOpType kType = PaintOpType::DrawText; static constexpr bool kIsDrawOp = true; DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags) @@ -625,15 +775,20 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); void* GetData() { return GetDataForThis(this); } const void* GetData() const { return GetDataForThis(this); } SkScalar x; SkScalar y; + + private: + DrawTextOp() = default; }; -struct CC_PAINT_EXPORT DrawTextBlobOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawTextBlobOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawTextBlob; static constexpr bool kIsDrawOp = true; DrawTextBlobOp(sk_sp<SkTextBlob> blob, @@ -651,44 +806,60 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); sk_sp<SkTextBlob> blob; SkScalar x; SkScalar y; + + private: + DrawTextBlobOp(); }; -struct CC_PAINT_EXPORT NoopOp final : PaintOp { +class CC_PAINT_EXPORT NoopOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Noop; static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm) {} + HAS_SERIALIZATION_FUNCTIONS(); }; -struct CC_PAINT_EXPORT RestoreOp final : PaintOp { +class CC_PAINT_EXPORT RestoreOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Restore; static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); }; -struct CC_PAINT_EXPORT RotateOp final : PaintOp { +class CC_PAINT_EXPORT RotateOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Rotate; explicit RotateOp(SkScalar degrees) : degrees(degrees) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar degrees; + + private: + RotateOp() = default; }; -struct CC_PAINT_EXPORT SaveOp final : PaintOp { +class CC_PAINT_EXPORT SaveOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Save; static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); }; -struct CC_PAINT_EXPORT SaveLayerOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT SaveLayerOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::SaveLayer; SaveLayerOp(const SkRect* bounds, const PaintFlags* flags) : PaintOpWithFlags(flags ? *flags : PaintFlags()), @@ -704,11 +875,16 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasNonAAPaint() const { return false; } + HAS_SERIALIZATION_FUNCTIONS(); SkRect bounds; + + private: + SaveLayerOp() = default; }; -struct CC_PAINT_EXPORT SaveLayerAlphaOp final : PaintOp { +class CC_PAINT_EXPORT SaveLayerAlphaOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha; SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha, @@ -719,24 +895,34 @@ static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect bounds; uint8_t alpha; bool preserve_lcd_text_requests; + + private: + SaveLayerAlphaOp() = default; }; -struct CC_PAINT_EXPORT ScaleOp final : PaintOp { +class CC_PAINT_EXPORT ScaleOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Scale; ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar sx; SkScalar sy; + + private: + ScaleOp() = default; }; -struct CC_PAINT_EXPORT SetMatrixOp final : PaintOp { +class CC_PAINT_EXPORT SetMatrixOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::SetMatrix; explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {} // This is the only op that needs the original ctm of the SkCanvas @@ -748,21 +934,32 @@ static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; + + private: + SetMatrixOp() = default; }; -struct CC_PAINT_EXPORT TranslateOp final : PaintOp { +class CC_PAINT_EXPORT TranslateOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Translate; TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar dx; SkScalar dy; + + private: + TranslateOp() = default; }; +#undef HAS_SERIALIZATION_FUNCTIONS + using LargestPaintOp = DrawDRRectOp; class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 913db86..ac1181ca 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -4,10 +4,12 @@ #include "cc/paint/paint_op_buffer.h" #include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" #include "cc/paint/display_item_list.h" #include "cc/test/skia_common.h" #include "cc/test/test_skcanvas.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkWriteBuffer.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" using testing::_; @@ -916,4 +918,1148 @@ buffer.Playback(&canvas); } +std::vector<float> test_floats = {0.f, + 1.f, + -1.f, + 2384.981971f, + 0.0001f, + std::numeric_limits<float>::min(), + std::numeric_limits<float>::max(), + std::numeric_limits<float>::infinity()}; + +std::vector<uint8_t> test_uint8s = { + 0, 255, 128, 10, 45, +}; + +std::vector<SkRect> test_rects = { + SkRect::MakeXYWH(1, 2.5, 3, 4), SkRect::MakeXYWH(0, 0, 0, 0), + SkRect::MakeLargest(), SkRect::MakeXYWH(0.5f, 0.5f, 8.2f, 8.2f), + SkRect::MakeXYWH(-1, -1, 0, 0), SkRect::MakeXYWH(-100, -101, -102, -103)}; + +std::vector<SkRRect> test_rrects = { + SkRRect::MakeEmpty(), SkRRect::MakeOval(SkRect::MakeXYWH(1, 2, 3, 4)), + SkRRect::MakeRect(SkRect::MakeXYWH(-10, 100, 5, 4)), + [] { + SkRRect rrect = SkRRect::MakeEmpty(); + rrect.setNinePatch(SkRect::MakeXYWH(10, 20, 30, 40), 1, 2, 3, 4); + return rrect; + }(), +}; + +std::vector<SkIRect> test_irects = { + SkIRect::MakeXYWH(1, 2, 3, 4), SkIRect::MakeXYWH(0, 0, 0, 0), + SkIRect::MakeLargest(), SkIRect::MakeXYWH(0, 0, 10, 10), + SkIRect::MakeXYWH(-1, -1, 0, 0), SkIRect::MakeXYWH(-100, -101, -102, -103)}; + +std::vector<SkMatrix> test_matrices = { + SkMatrix(), + SkMatrix::MakeScale(3.91f, 4.31f), + SkMatrix::MakeTrans(-5.2f, 8.7f), + [] { + SkMatrix matrix; + SkScalar buffer[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + matrix.set9(buffer); + return matrix; + }(), + [] { + SkMatrix matrix; + SkScalar buffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + matrix.set9(buffer); + return matrix; + }(), +}; + +std::vector<SkPath> test_paths = { + [] { + SkPath path; + path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); + path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); + path.lineTo(SkIntToScalar(30), SkIntToScalar(30)); + path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); + return path; + }(), + [] { + SkPath path; + path.addCircle(2, 2, 5); + path.addCircle(3, 4, 2); + path.addArc(SkRect::MakeXYWH(1, 2, 3, 4), 5, 6); + return path; + }(), + SkPath(), +}; + +// TODO(enne): make this more real. +std::vector<PaintFlags> test_flags = { + PaintFlags(), PaintFlags(), PaintFlags(), PaintFlags(), PaintFlags(), +}; + +std::vector<SkColor> test_colors = { + SkColorSetARGBInline(0, 0, 0, 0), + SkColorSetARGBInline(255, 255, 255, 255), + SkColorSetARGBInline(0, 255, 10, 255), + SkColorSetARGBInline(255, 0, 20, 255), + SkColorSetARGBInline(30, 255, 0, 255), + SkColorSetARGBInline(255, 40, 0, 0), +}; + +std::vector<std::string> test_strings = { + "", "foobar", + "blarbideeblarasdfaiousydfp234poiausdofiuapsodfjknla;sdfkjasd;f", +}; + +std::vector<std::vector<SkPoint>> test_point_arrays = { + std::vector<SkPoint>(), + {SkPoint::Make(1, 2)}, + {SkPoint::Make(1, 2), SkPoint::Make(-5.4f, -3.8f)}, + {SkPoint::Make(0, 0), SkPoint::Make(5, 6), SkPoint::Make(-1, -1), + SkPoint::Make(9, 9), SkPoint::Make(50, 50), SkPoint::Make(100, 100)}, +}; + +std::vector<sk_sp<SkTextBlob>> test_blobs = { + [] { + SkPaint font; + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + SkTextBlobBuilder builder; + builder.allocRun(font, 5, 1.2f, 2.3f, &test_rects[0]); + return builder.make(); + }(), + [] { + SkPaint font; + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + SkTextBlobBuilder builder; + builder.allocRun(font, 5, 1.2f, 2.3f, &test_rects[0]); + builder.allocRunPos(font, 16, &test_rects[1]); + builder.allocRunPosH(font, 8, 0, &test_rects[2]); + return builder.make(); + }(), +}; + +// TODO(enne): In practice, probably all paint images need to be uploaded +// ahead of time and not be bitmaps. These paint images should be fake +// gpu resource paint images. +std::vector<PaintImage> test_images = { + PaintImage(PaintImage::GetNextId(), + CreateDiscardableImage(gfx::Size(5, 10))), + PaintImage(PaintImage::GetNextId(), + CreateDiscardableImage(gfx::Size(1, 1))), + PaintImage(PaintImage::GetNextId(), + CreateDiscardableImage(gfx::Size(50, 50))), +}; + +// Writes as many ops in |buffer| as can fit in |output_size| to |output|. +// Records the numbers of bytes written for each op. +class SimpleSerializer { + public: + SimpleSerializer(void* output, size_t output_size) + : current_(static_cast<char*>(output)), + output_size_(output_size), + remaining_(output_size) {} + + void Serialize(const PaintOpBuffer& buffer) { + bytes_written_.resize(buffer.size()); + for (size_t i = 0; i < buffer.size(); ++i) + bytes_written_[i] = 0; + + PaintOp::SerializeOptions options; + + size_t op_idx = 0; + for (const auto* op : PaintOpBuffer::Iterator(&buffer)) { + size_t bytes_written = op->Serialize(current_, remaining_, options); + if (!bytes_written) + return; + + PaintOp* written = reinterpret_cast<PaintOp*>(current_); + EXPECT_EQ(op->GetType(), written->GetType()); + EXPECT_EQ(bytes_written, written->skip); + + bytes_written_[op_idx] = bytes_written; + op_idx++; + current_ += bytes_written; + remaining_ -= bytes_written; + + // Number of bytes bytes_written must be a multiple of PaintOpAlign + // unless the buffer is filled entirely. + if (remaining_ != 0u) + DCHECK_EQ(0u, bytes_written % PaintOpBuffer::PaintOpAlign); + } + } + + const std::vector<size_t>& bytes_written() const { return bytes_written_; } + size_t TotalBytesWritten() const { return output_size_ - remaining_; } + + private: + char* current_ = nullptr; + size_t output_size_ = 0u; + size_t remaining_ = 0u; + std::vector<size_t> bytes_written_; +}; + +class DeserializerIterator { + public: + DeserializerIterator(const void* input, size_t input_size) + : DeserializerIterator(input, + static_cast<const char*>(input), + input_size, + input_size) {} + + DeserializerIterator(DeserializerIterator&&) = default; + DeserializerIterator& operator=(DeserializerIterator&&) = default; + + ~DeserializerIterator() { DestroyDeserializedOp(); } + + DeserializerIterator begin() { + return DeserializerIterator(input_, static_cast<const char*>(input_), + input_size_, input_size_); + } + DeserializerIterator end() { + return DeserializerIterator( + input_, static_cast<const char*>(input_) + input_size_, input_size_, 0); + } + bool operator!=(const DeserializerIterator& other) { + return input_ != other.input_ || current_ != other.current_ || + input_size_ != other.input_size_ || remaining_ != other.remaining_; + } + DeserializerIterator& operator++() { + const PaintOp* serialized = reinterpret_cast<const PaintOp*>(current_); + + CHECK_GE(remaining_, serialized->skip); + current_ += serialized->skip; + remaining_ -= serialized->skip; + + if (remaining_ > 0) + CHECK_GE(remaining_, 4u); + + DeserializeCurrentOp(); + + return *this; + } + + operator bool() const { return remaining_ == 0u; } + const PaintOp* operator->() const { return deserialized_op_; } + const PaintOp* operator*() const { return deserialized_op_; } + + private: + DeserializerIterator(const void* input, + const char* current, + size_t input_size, + size_t remaining) + : input_(input), + current_(current), + input_size_(input_size), + remaining_(remaining) { + DeserializeCurrentOp(); + } + + void DestroyDeserializedOp() { + if (!deserialized_op_) + return; + deserialized_op_->DestroyThis(); + deserialized_op_ = nullptr; + } + + void DeserializeCurrentOp() { + DestroyDeserializedOp(); + + if (!remaining_) + return; + + const PaintOp* serialized = reinterpret_cast<const PaintOp*>(current_); + size_t required = sizeof(LargestPaintOp) + serialized->skip; + + if (data_size_ < required) { + data_.reset(static_cast<char*>( + base::AlignedAlloc(required, PaintOpBuffer::PaintOpAlign))); + data_size_ = required; + } + deserialized_op_ = + PaintOp::Deserialize(current_, remaining_, data_.get(), data_size_); + } + + const void* input_ = nullptr; + const char* current_ = nullptr; + size_t input_size_ = 0u; + size_t remaining_ = 0u; + std::unique_ptr<char, base::AlignedFreeDeleter> data_; + size_t data_size_ = 0u; + PaintOp* deserialized_op_ = nullptr; +}; + +void PushAnnotateOps(PaintOpBuffer* buffer) { + buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::URL, test_rects[0], + SkData::MakeWithCString("thingerdoowhatchamagig")); + // Deliberately test both null and empty SkData. + buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::LINK_TO_DESTINATION, + test_rects[1], nullptr); + buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::NAMED_DESTINATION, + test_rects[2], SkData::MakeEmpty()); +} + +void PushClipPathOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_paths.size(); ++i) { + SkClipOp op = i % 3 ? SkClipOp::kDifference : SkClipOp::kIntersect; + buffer->push<ClipPathOp>(test_paths[i], op, !!(i % 2)); + } +} + +void PushClipRectOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_rects.size(); ++i) { + SkClipOp op = i % 2 ? SkClipOp::kIntersect : SkClipOp::kDifference; + bool antialias = !!(i % 3); + buffer->push<ClipRectOp>(test_rects[i], op, antialias); + } +} + +void PushClipRRectOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_rrects.size(); ++i) { + SkClipOp op = i % 2 ? SkClipOp::kIntersect : SkClipOp::kDifference; + bool antialias = !!(i % 3); + buffer->push<ClipRRectOp>(test_rrects[i], op, antialias); + } +} + +void PushConcatOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_matrices.size(); ++i) + buffer->push<ConcatOp>(test_matrices[i]); +} + +void PushDrawArcOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_floats.size() - 1, test_flags.size()), + test_rects.size()); + for (size_t i = 0; i < len; ++i) { + bool use_center = !!(i % 2); + buffer->push<DrawArcOp>(test_rects[i], test_floats[i], test_floats[i + 1], + use_center, test_flags[i]); + } +} + +void PushDrawCircleOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_floats.size() - 2, test_flags.size()); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawCircleOp>(test_floats[i], test_floats[i + 1], + test_floats[i + 2], test_flags[i]); + } +} + +void PushDrawColorOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_colors.size(); ++i) { + buffer->push<DrawColorOp>(test_colors[i], static_cast<SkBlendMode>(i)); + } +} + +void PushDrawDRRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_rrects.size() - 1, test_flags.size()); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawDRRectOp>(test_rrects[i], test_rrects[i + 1], + test_flags[i]); + } +} + +void PushDrawImageOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_images.size(), test_flags.size()), + test_floats.size() - 1); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawImageOp>(test_images[i], test_floats[i], + test_floats[i + 1], &test_flags[i]); + } + + // Test optional flags + // TODO(enne): maybe all these optional ops should not be optional. + buffer->push<DrawImageOp>(test_images[0], test_floats[0], test_floats[1], + nullptr); +} + +void PushDrawImageRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_images.size(), test_flags.size()), + test_rects.size() - 1); + for (size_t i = 0; i < len; ++i) { + PaintCanvas::SrcRectConstraint constraint = + i % 2 ? PaintCanvas::kStrict_SrcRectConstraint + : PaintCanvas::kFast_SrcRectConstraint; + buffer->push<DrawImageRectOp>(test_images[i], test_rects[i], + test_rects[i + 1], &test_flags[i], + constraint); + } + + // Test optional flags. + buffer->push<DrawImageRectOp>(test_images[0], test_rects[0], test_rects[1], + nullptr, + PaintCanvas::kStrict_SrcRectConstraint); +} + +void PushDrawIRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_irects.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawIRectOp>(test_irects[i], test_flags[i]); +} + +void PushDrawLineOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_floats.size() - 3, test_flags.size()); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawLineOp>(test_floats[i], test_floats[i + 1], + test_floats[i + 2], test_floats[i + 3], + test_flags[i]); + } +} + +void PushDrawOvalOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_paths.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawOvalOp>(test_rects[i], test_flags[i]); +} + +void PushDrawPathOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_paths.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawPathOp>(test_paths[i], test_flags[i]); +} + +void PushDrawPosTextOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_flags.size(), test_strings.size()), + test_point_arrays.size()); + for (size_t i = 0; i < len; ++i) { + // Make sure empty array works fine. + SkPoint* array = + test_point_arrays[i].size() > 0 ? &test_point_arrays[i][0] : nullptr; + buffer->push_with_array<DrawPosTextOp>( + test_strings[i].c_str(), test_strings[i].size() + 1, array, + test_point_arrays[i].size(), test_flags[i]); + } +} + +void PushDrawRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_rects.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawRectOp>(test_rects[i], test_flags[i]); +} + +void PushDrawRRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_rrects.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawRRectOp>(test_rrects[i], test_flags[i]); +} + +void PushDrawTextOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_strings.size(), test_flags.size()), + test_floats.size() - 1); + for (size_t i = 0; i < len; ++i) { + buffer->push_with_data<DrawTextOp>( + test_strings[i].c_str(), test_strings[i].size() + 1, test_floats[i], + test_floats[i + 1], test_flags[i]); + } +} + +void PushDrawTextBlobOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_blobs.size(), test_flags.size()), + test_floats.size() - 1); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawTextBlobOp>(test_blobs[i], test_floats[i], + test_floats[i + 1], test_flags[i]); + } +} + +void PushNoopOps(PaintOpBuffer* buffer) { + buffer->push<NoopOp>(); + buffer->push<NoopOp>(); + buffer->push<NoopOp>(); + buffer->push<NoopOp>(); +} + +void PushRestoreOps(PaintOpBuffer* buffer) { + buffer->push<RestoreOp>(); + buffer->push<RestoreOp>(); + buffer->push<RestoreOp>(); + buffer->push<RestoreOp>(); +} + +void PushRotateOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_floats.size(); ++i) + buffer->push<RotateOp>(test_floats[i]); +} + +void PushSaveOps(PaintOpBuffer* buffer) { + buffer->push<SaveOp>(); + buffer->push<SaveOp>(); + buffer->push<SaveOp>(); + buffer->push<SaveOp>(); +} + +void PushSaveLayerOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_flags.size(), test_rects.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<SaveLayerOp>(&test_rects[i], &test_flags[i]); + + // Test combinations of optional args. + buffer->push<SaveLayerOp>(nullptr, &test_flags[0]); + buffer->push<SaveLayerOp>(&test_rects[0], nullptr); + buffer->push<SaveLayerOp>(nullptr, nullptr); +} + +void PushSaveLayerAlphaOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_uint8s.size(), test_rects.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<SaveLayerAlphaOp>(&test_rects[i], test_uint8s[i], !!(i % 2)); + + // Test optional args. + buffer->push<SaveLayerAlphaOp>(nullptr, test_uint8s[0], false); +} + +void PushScaleOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_floats.size(); i += 2) + buffer->push<ScaleOp>(test_floats[i], test_floats[i + 1]); +} + +void PushSetMatrixOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_matrices.size(); ++i) + buffer->push<SetMatrixOp>(test_matrices[i]); +} + +void PushTranslateOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_floats.size(); i += 2) + buffer->push<TranslateOp>(test_floats[i], test_floats[i + 1]); +} + +void CompareFlags(const PaintFlags& original, const PaintFlags& written) {} + +void CompareImages(const PaintImage& original, const PaintImage& written) {} + +void CompareAnnotateOp(const AnnotateOp* original, const AnnotateOp* written) { + EXPECT_EQ(original->annotation_type, written->annotation_type); + EXPECT_EQ(original->rect, written->rect); + EXPECT_EQ(!!original->data, !!written->data); + if (original->data) { + EXPECT_EQ(original->data->size(), written->data->size()); + EXPECT_EQ(0, memcmp(original->data->data(), written->data->data(), + written->data->size())); + } +} + +void CompareClipPathOp(const ClipPathOp* original, const ClipPathOp* written) { + EXPECT_TRUE(original->path == written->path); + EXPECT_EQ(original->op, written->op); + EXPECT_EQ(original->antialias, written->antialias); +} + +void CompareClipRectOp(const ClipRectOp* original, const ClipRectOp* written) { + EXPECT_EQ(original->rect, written->rect); + EXPECT_EQ(original->op, written->op); + EXPECT_EQ(original->antialias, written->antialias); +} + +void CompareClipRRectOp(const ClipRRectOp* original, + const ClipRRectOp* written) { + EXPECT_EQ(original->rrect, written->rrect); + EXPECT_EQ(original->op, written->op); + EXPECT_EQ(original->antialias, written->antialias); +} + +void CompareConcatOp(const ConcatOp* original, const ConcatOp* written) { + EXPECT_EQ(original->matrix, written->matrix); + EXPECT_EQ(original->matrix.getType(), written->matrix.getType()); +} + +void CompareDrawArcOp(const DrawArcOp* original, const DrawArcOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->oval, written->oval); + EXPECT_EQ(original->start_angle, written->start_angle); + EXPECT_EQ(original->sweep_angle, written->sweep_angle); + EXPECT_EQ(original->use_center, written->use_center); +} + +void CompareDrawCircleOp(const DrawCircleOp* original, + const DrawCircleOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->cx, written->cx); + EXPECT_EQ(original->cy, written->cy); + EXPECT_EQ(original->radius, written->radius); +} + +void CompareDrawColorOp(const DrawColorOp* original, + const DrawColorOp* written) { + EXPECT_EQ(original->color, written->color); +} + +void CompareDrawDRRectOp(const DrawDRRectOp* original, + const DrawDRRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->outer, written->outer); + EXPECT_EQ(original->inner, written->inner); +} + +void CompareDrawImageOp(const DrawImageOp* original, + const DrawImageOp* written) { + CompareFlags(original->flags, written->flags); + CompareImages(original->image, written->image); + EXPECT_EQ(original->left, written->left); + EXPECT_EQ(original->top, written->top); +} + +void CompareDrawImageRectOp(const DrawImageRectOp* original, + const DrawImageRectOp* written) { + CompareFlags(original->flags, written->flags); + CompareImages(original->image, written->image); + EXPECT_EQ(original->src, written->src); + EXPECT_EQ(original->dst, written->dst); +} + +void CompareDrawIRectOp(const DrawIRectOp* original, + const DrawIRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->rect, written->rect); +} + +void CompareDrawLineOp(const DrawLineOp* original, const DrawLineOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->x0, written->x0); + EXPECT_EQ(original->y0, written->y0); + EXPECT_EQ(original->x1, written->x1); + EXPECT_EQ(original->y1, written->y1); +} + +void CompareDrawOvalOp(const DrawOvalOp* original, const DrawOvalOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->oval, written->oval); +} + +void CompareDrawPathOp(const DrawPathOp* original, const DrawPathOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_TRUE(original->path == written->path); +} + +void CompareDrawPosTextOp(const DrawPosTextOp* original, + const DrawPosTextOp* written) { + CompareFlags(original->flags, written->flags); + ASSERT_EQ(original->bytes, written->bytes); + EXPECT_EQ(std::string(static_cast<const char*>(original->GetData())), + std::string(static_cast<const char*>(written->GetData()))); + ASSERT_EQ(original->count, written->count); + for (size_t i = 0; i < original->count; ++i) + EXPECT_EQ(original->GetArray()[i], written->GetArray()[i]); +} + +void CompareDrawRectOp(const DrawRectOp* original, const DrawRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->rect, written->rect); +} + +void CompareDrawRRectOp(const DrawRRectOp* original, + const DrawRRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->rrect, written->rrect); +} + +void CompareDrawTextOp(const DrawTextOp* original, const DrawTextOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->x, written->x); + EXPECT_EQ(original->y, written->y); + ASSERT_EQ(original->bytes, written->bytes); + EXPECT_EQ(std::string(static_cast<const char*>(original->GetData())), + std::string(static_cast<const char*>(written->GetData()))); +} + +void CompareDrawTextBlobOp(const DrawTextBlobOp* original, + const DrawTextBlobOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->x, written->x); + EXPECT_EQ(original->y, written->y); + + // TODO(enne): implement SkTextBlob serialization: http://crbug.com/737629 + if (!original->blob || !written->blob) + return; + + ASSERT_TRUE(original->blob); + ASSERT_TRUE(written->blob); + + // No text blob operator==, so flatten them both and compare. + size_t max_size = original->skip; + + std::vector<char> original_mem; + original_mem.resize(max_size); + SkBinaryWriteBuffer original_flattened(&original_mem[0], max_size); + original->blob->flatten(original_flattened); + original_mem.resize(original_flattened.bytesWritten()); + + std::vector<char> written_mem; + written_mem.resize(max_size); + SkBinaryWriteBuffer written_flattened(&written_mem[0], max_size); + written->blob->flatten(written_flattened); + written_mem.resize(written_flattened.bytesWritten()); + + ASSERT_EQ(original_mem.size(), written_mem.size()); + EXPECT_EQ(original_mem, written_mem); +} + +void CompareNoopOp(const NoopOp* original, const NoopOp* written) { + // Nothing to compare. +} + +void CompareRestoreOp(const RestoreOp* original, const RestoreOp* written) { + // Nothing to compare. +} + +void CompareRotateOp(const RotateOp* original, const RotateOp* written) { + EXPECT_EQ(original->degrees, written->degrees); +} + +void CompareSaveOp(const SaveOp* original, const SaveOp* written) { + // Nothing to compare. +} + +void CompareSaveLayerOp(const SaveLayerOp* original, + const SaveLayerOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->bounds, written->bounds); +} + +void CompareSaveLayerAlphaOp(const SaveLayerAlphaOp* original, + const SaveLayerAlphaOp* written) { + EXPECT_EQ(original->bounds, written->bounds); + EXPECT_EQ(original->alpha, written->alpha); + EXPECT_EQ(original->preserve_lcd_text_requests, + written->preserve_lcd_text_requests); +} + +void CompareScaleOp(const ScaleOp* original, const ScaleOp* written) { + EXPECT_EQ(original->sx, written->sx); + EXPECT_EQ(original->sy, written->sy); +} + +void CompareSetMatrixOp(const SetMatrixOp* original, + const SetMatrixOp* written) { + EXPECT_EQ(original->matrix, written->matrix); +} + +void CompareTranslateOp(const TranslateOp* original, + const TranslateOp* written) { + EXPECT_EQ(original->dx, written->dx); + EXPECT_EQ(original->dy, written->dy); +} + +class PaintOpSerializationTest : public ::testing::TestWithParam<uint8_t> { + public: + PaintOpType GetParamType() const { + return static_cast<PaintOpType>(GetParam()); + } + + void PushTestOps(PaintOpType type) { + switch (type) { + case PaintOpType::Annotate: + PushAnnotateOps(&buffer_); + break; + case PaintOpType::ClipPath: + PushClipPathOps(&buffer_); + break; + case PaintOpType::ClipRect: + PushClipRectOps(&buffer_); + break; + case PaintOpType::ClipRRect: + PushClipRRectOps(&buffer_); + break; + case PaintOpType::Concat: + PushConcatOps(&buffer_); + break; + case PaintOpType::DrawArc: + PushDrawArcOps(&buffer_); + break; + case PaintOpType::DrawCircle: + PushDrawCircleOps(&buffer_); + break; + case PaintOpType::DrawColor: + PushDrawColorOps(&buffer_); + break; + case PaintOpType::DrawDRRect: + PushDrawDRRectOps(&buffer_); + break; + case PaintOpType::DrawImage: + PushDrawImageOps(&buffer_); + break; + case PaintOpType::DrawImageRect: + PushDrawImageRectOps(&buffer_); + break; + case PaintOpType::DrawIRect: + PushDrawIRectOps(&buffer_); + break; + case PaintOpType::DrawLine: + PushDrawLineOps(&buffer_); + break; + case PaintOpType::DrawOval: + PushDrawOvalOps(&buffer_); + break; + case PaintOpType::DrawPath: + PushDrawPathOps(&buffer_); + break; + case PaintOpType::DrawPosText: + PushDrawPosTextOps(&buffer_); + break; + case PaintOpType::DrawRecord: + // Not supported. + break; + case PaintOpType::DrawRect: + PushDrawRectOps(&buffer_); + break; + case PaintOpType::DrawRRect: + PushDrawRRectOps(&buffer_); + break; + case PaintOpType::DrawText: + PushDrawTextOps(&buffer_); + break; + case PaintOpType::DrawTextBlob: + PushDrawTextBlobOps(&buffer_); + break; + case PaintOpType::Noop: + PushNoopOps(&buffer_); + break; + case PaintOpType::Restore: + PushRestoreOps(&buffer_); + break; + case PaintOpType::Rotate: + PushRotateOps(&buffer_); + break; + case PaintOpType::Save: + PushSaveOps(&buffer_); + break; + case PaintOpType::SaveLayer: + PushSaveLayerOps(&buffer_); + break; + case PaintOpType::SaveLayerAlpha: + PushSaveLayerAlphaOps(&buffer_); + break; + case PaintOpType::Scale: + PushScaleOps(&buffer_); + break; + case PaintOpType::SetMatrix: + PushSetMatrixOps(&buffer_); + break; + case PaintOpType::Translate: + PushTranslateOps(&buffer_); + break; + } + } + + static void ExpectOpsEqual(const PaintOp* original, const PaintOp* written) { + ASSERT_TRUE(original); + ASSERT_TRUE(written); + ASSERT_EQ(original->GetType(), written->GetType()); + EXPECT_EQ(original->skip, written->skip); + + switch (original->GetType()) { + case PaintOpType::Annotate: + CompareAnnotateOp(static_cast<const AnnotateOp*>(original), + static_cast<const AnnotateOp*>(written)); + break; + case PaintOpType::ClipPath: + CompareClipPathOp(static_cast<const ClipPathOp*>(original), + static_cast<const ClipPathOp*>(written)); + break; + case PaintOpType::ClipRect: + CompareClipRectOp(static_cast<const ClipRectOp*>(original), + static_cast<const ClipRectOp*>(written)); + break; + case PaintOpType::ClipRRect: + CompareClipRRectOp(static_cast<const ClipRRectOp*>(original), + static_cast<const ClipRRectOp*>(written)); + break; + case PaintOpType::Concat: + CompareConcatOp(static_cast<const ConcatOp*>(original), + static_cast<const ConcatOp*>(written)); + break; + case PaintOpType::DrawArc: + CompareDrawArcOp(static_cast<const DrawArcOp*>(original), + static_cast<const DrawArcOp*>(written)); + break; + case PaintOpType::DrawCircle: + CompareDrawCircleOp(static_cast<const DrawCircleOp*>(original), + static_cast<const DrawCircleOp*>(written)); + break; + case PaintOpType::DrawColor: + CompareDrawColorOp(static_cast<const DrawColorOp*>(original), + static_cast<const DrawColorOp*>(written)); + break; + case PaintOpType::DrawDRRect: + CompareDrawDRRectOp(static_cast<const DrawDRRectOp*>(original), + static_cast<const DrawDRRectOp*>(written)); + break; + case PaintOpType::DrawImage: + CompareDrawImageOp(static_cast<const DrawImageOp*>(original), + static_cast<const DrawImageOp*>(written)); + break; + case PaintOpType::DrawImageRect: + CompareDrawImageRectOp(static_cast<const DrawImageRectOp*>(original), + static_cast<const DrawImageRectOp*>(written)); + break; + case PaintOpType::DrawIRect: + CompareDrawIRectOp(static_cast<const DrawIRectOp*>(original), + static_cast<const DrawIRectOp*>(written)); + break; + case PaintOpType::DrawLine: + CompareDrawLineOp(static_cast<const DrawLineOp*>(original), + static_cast<const DrawLineOp*>(written)); + break; + case PaintOpType::DrawOval: + CompareDrawOvalOp(static_cast<const DrawOvalOp*>(original), + static_cast<const DrawOvalOp*>(written)); + break; + case PaintOpType::DrawPath: + CompareDrawPathOp(static_cast<const DrawPathOp*>(original), + static_cast<const DrawPathOp*>(written)); + break; + case PaintOpType::DrawPosText: + CompareDrawPosTextOp(static_cast<const DrawPosTextOp*>(original), + static_cast<const DrawPosTextOp*>(written)); + break; + case PaintOpType::DrawRecord: + // Not supported. + break; + case PaintOpType::DrawRect: + CompareDrawRectOp(static_cast<const DrawRectOp*>(original), + static_cast<const DrawRectOp*>(written)); + break; + case PaintOpType::DrawRRect: + CompareDrawRRectOp(static_cast<const DrawRRectOp*>(original), + static_cast<const DrawRRectOp*>(written)); + break; + case PaintOpType::DrawText: + CompareDrawTextOp(static_cast<const DrawTextOp*>(original), + static_cast<const DrawTextOp*>(written)); + break; + case PaintOpType::DrawTextBlob: + CompareDrawTextBlobOp(static_cast<const DrawTextBlobOp*>(original), + static_cast<const DrawTextBlobOp*>(written)); + break; + case PaintOpType::Noop: + CompareNoopOp(static_cast<const NoopOp*>(original), + static_cast<const NoopOp*>(written)); + break; + case PaintOpType::Restore: + CompareRestoreOp(static_cast<const RestoreOp*>(original), + static_cast<const RestoreOp*>(written)); + break; + case PaintOpType::Rotate: + CompareRotateOp(static_cast<const RotateOp*>(original), + static_cast<const RotateOp*>(written)); + break; + case PaintOpType::Save: + CompareSaveOp(static_cast<const SaveOp*>(original), + static_cast<const SaveOp*>(written)); + break; + case PaintOpType::SaveLayer: + CompareSaveLayerOp(static_cast<const SaveLayerOp*>(original), + static_cast<const SaveLayerOp*>(written)); + break; + case PaintOpType::SaveLayerAlpha: + CompareSaveLayerAlphaOp(static_cast<const SaveLayerAlphaOp*>(original), + static_cast<const SaveLayerAlphaOp*>(written)); + break; + case PaintOpType::Scale: + CompareScaleOp(static_cast<const ScaleOp*>(original), + static_cast<const ScaleOp*>(written)); + break; + case PaintOpType::SetMatrix: + CompareSetMatrixOp(static_cast<const SetMatrixOp*>(original), + static_cast<const SetMatrixOp*>(written)); + break; + case PaintOpType::Translate: + CompareTranslateOp(static_cast<const TranslateOp*>(original), + static_cast<const TranslateOp*>(written)); + break; + } + } + + void ResizeOutputBuffer() { + // An arbitrary deserialization buffer size that should fit all the ops + // in the buffer_. + output_size_ = (100 + sizeof(LargestPaintOp)) * buffer_.size(); + output_.reset(static_cast<char*>( + base::AlignedAlloc(output_size_, PaintOpBuffer::PaintOpAlign))); + } + + bool IsTypeSupported() { + // DrawRecordOps must be flattened and are not currently serialized. + // All other types must push non-zero amounts of ops in PushTestOps. + return GetParamType() != PaintOpType::DrawRecord; + } + + protected: + std::unique_ptr<char, base::AlignedFreeDeleter> output_; + size_t output_size_ = 0u; + PaintOpBuffer buffer_; +}; + +INSTANTIATE_TEST_CASE_P( + P, + PaintOpSerializationTest, + ::testing::Range(static_cast<uint8_t>(0), + static_cast<uint8_t>(PaintOpType::LastPaintOpType))); + +// Test serializing and then deserializing all test ops. They should all +// write successfully and be identical to the original ops in the buffer. +TEST_P(PaintOpSerializationTest, SmokeTest) { + if (!IsTypeSupported()) + return; + + PushTestOps(GetParamType()); + + ResizeOutputBuffer(); + + SimpleSerializer serializer(output_.get(), output_size_); + serializer.Serialize(buffer_); + + // Expect all ops to write more than 0 bytes. + for (size_t i = 0; i < buffer_.size(); ++i) { + SCOPED_TRACE(base::StringPrintf( + "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), i)); + EXPECT_GT(serializer.bytes_written()[i], 0u); + } + + PaintOpBuffer::Iterator iter(&buffer_); + for (auto* base_written : + DeserializerIterator(output_.get(), serializer.TotalBytesWritten())) { + SCOPED_TRACE(base::StringPrintf( + "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), iter.op_idx())); + ExpectOpsEqual(*iter, base_written); + ++iter; + } + + EXPECT_EQ(buffer_.size(), iter.op_idx()); +} + +// Verify for all test ops that serializing into a smaller size aborts +// correctly and doesn't write anything. +TEST_P(PaintOpSerializationTest, SerializationFailures) { + if (!IsTypeSupported()) + return; + + PushTestOps(GetParamType()); + + ResizeOutputBuffer(); + + SimpleSerializer serializer(output_.get(), output_size_); + serializer.Serialize(buffer_); + std::vector<size_t> bytes_written = serializer.bytes_written(); + + PaintOp::SerializeOptions options; + + for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter) { + SCOPED_TRACE(base::StringPrintf( + "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), iter.op_idx())); + size_t expected_bytes = bytes_written[iter.op_idx()]; + EXPECT_GT(expected_bytes, 0u); + + // Attempt to write op into a buffer of size |i|, and only expect + // it to succeed if the buffer is large enough. + for (size_t i = 0; i < bytes_written[iter.op_idx()] + 2; ++i) { + size_t written_bytes = iter->Serialize(output_.get(), i, options); + if (i >= expected_bytes) { + EXPECT_EQ(expected_bytes, written_bytes) << "i: " << i; + } else { + EXPECT_EQ(0u, written_bytes) << "i: " << i; + } + } + } +} + +// Verify that deserializing test ops from too small buffers aborts +// correctly, in case the deserialized data is lying about how big it is. +TEST_P(PaintOpSerializationTest, DeserializationFailures) { + if (!IsTypeSupported()) + return; + + PushTestOps(GetParamType()); + + ResizeOutputBuffer(); + + SimpleSerializer serializer(output_.get(), output_size_); + serializer.Serialize(buffer_); + + char* current = static_cast<char*>(output_.get()); + + static constexpr size_t kAlign = PaintOpBuffer::PaintOpAlign; + static constexpr size_t kOutputOpSize = sizeof(LargestPaintOp) + 100; + std::unique_ptr<char, base::AlignedFreeDeleter> deserialize_buffer_( + static_cast<char*>(base::AlignedAlloc(kOutputOpSize, kAlign))); + + for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter) { + PaintOp* serialized = reinterpret_cast<PaintOp*>(current); + uint32_t skip = serialized->skip; + + // Read from buffers of various sizes to make sure that having a serialized + // op size that is larger than the input buffer provided causes a + // deserialization failure to return nullptr. Also test a few valid sizes + // larger than read size. + for (size_t read_size = 0; read_size < skip + kAlign * 2 + 2; ++read_size) { + SCOPED_TRACE( + base::StringPrintf("%s #%zd, read_size: %zd", + PaintOpTypeToString(GetParamType()).c_str(), + iter.op_idx(), read_size)); + // Because PaintOp::Deserialize early outs when the input size is < skip + // deliberately lie about the skip. This op tooooootally fits. + // This will verify that individual op deserializing code behaves + // properly when presented with invalid offsets. + serialized->skip = read_size; + PaintOp* written = PaintOp::Deserialize( + current, read_size, deserialize_buffer_.get(), kOutputOpSize); + + // Skips are only valid if they are aligned. + if (read_size >= skip && read_size % kAlign == 0) { + ASSERT_NE(nullptr, written); + ASSERT_LE(written->skip, kOutputOpSize); + EXPECT_EQ(GetParamType(), written->GetType()); + } else { + EXPECT_EQ(nullptr, written); + } + + if (written) + written->DestroyThis(); + } + + current += skip; + } +} + +// Test generic PaintOp deserializing failure cases. +TEST(PaintOpBufferTest, PaintOpDeserialize) { + static constexpr size_t kSize = sizeof(LargestPaintOp) + 100; + static constexpr size_t kAlign = PaintOpBuffer::PaintOpAlign; + std::unique_ptr<char, base::AlignedFreeDeleter> input_( + static_cast<char*>(base::AlignedAlloc(kSize, kAlign))); + std::unique_ptr<char, base::AlignedFreeDeleter> output_( + static_cast<char*>(base::AlignedAlloc(kSize, kAlign))); + + PaintOpBuffer buffer; + buffer.push<DrawColorOp>(SK_ColorMAGENTA, SkBlendMode::kSrc); + + PaintOpBuffer::Iterator iter(&buffer); + PaintOp* op = *iter; + ASSERT_TRUE(op); + + PaintOp::SerializeOptions options; + size_t bytes_written = op->Serialize(input_.get(), kSize, options); + ASSERT_GT(bytes_written, 0u); + + // can deserialize from exactly the right size + PaintOp* success = + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize); + ASSERT_TRUE(success); + success->DestroyThis(); + + // fail to deserialize if skip goes past input size + // (the DeserializationFailures test above tests if the skip is lying) + for (size_t i = 0; i < bytes_written - 1; ++i) + EXPECT_FALSE(PaintOp::Deserialize(input_.get(), i, output_.get(), kSize)); + + // unaligned skips fail to deserialize + PaintOp* serialized = reinterpret_cast<PaintOp*>(input_.get()); + EXPECT_EQ(0u, serialized->skip % kAlign); + serialized->skip -= 1; + EXPECT_FALSE( + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize)); + serialized->skip += 1; + + // bogus types fail to deserialize + serialized->type = static_cast<uint8_t>(PaintOpType::LastPaintOpType) + 1; + EXPECT_FALSE( + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize)); +} + } // namespace cc
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc new file mode 100644 index 0000000..318974b --- /dev/null +++ b/cc/paint/paint_op_reader.cc
@@ -0,0 +1,130 @@ +// 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 "cc/paint/paint_op_reader.h" + +#include <stddef.h> + +#include "cc/paint/paint_flags.h" +#include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/core/SkRRect.h" +#include "third_party/skia/include/core/SkTextBlob.h" + +namespace cc { + +template <typename T> +void PaintOpReader::ReadSimple(T* val) { + if (remaining_bytes_ < sizeof(T)) + valid_ = false; + if (!valid_) + return; + + *val = reinterpret_cast<const T*>(memory_)[0]; + + memory_ += sizeof(T); + remaining_bytes_ -= sizeof(T); +} + +void PaintOpReader::ReadData(size_t bytes, void* data) { + if (remaining_bytes_ < bytes) + valid_ = false; + if (!valid_) + return; + if (bytes == 0) + return; + + memcpy(data, memory_, bytes); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpReader::ReadArray(size_t count, SkPoint* array) { + size_t bytes = count * sizeof(SkPoint); + if (remaining_bytes_ < bytes) + valid_ = false; + // Overflow? + if (count > static_cast<size_t>(~0) / sizeof(SkPoint)) + valid_ = false; + if (!valid_) + return; + if (count == 0) + return; + + memcpy(array, memory_, bytes); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpReader::Read(SkScalar* data) { + ReadSimple(data); +} + +void PaintOpReader::Read(size_t* data) { + ReadSimple(data); +} + +void PaintOpReader::Read(uint8_t* data) { + ReadSimple(data); +} + +void PaintOpReader::Read(SkRect* rect) { + ReadSimple(rect); +} + +void PaintOpReader::Read(SkIRect* rect) { + ReadSimple(rect); +} + +void PaintOpReader::Read(SkRRect* rect) { + ReadSimple(rect); +} + +void PaintOpReader::Read(SkPath* path) { + if (!valid_) + return; + + // TODO(enne): Should the writer write how many bytes it expects as well? + size_t read_bytes = path->readFromMemory(memory_, remaining_bytes_); + if (!read_bytes) + valid_ = false; + + memory_ += read_bytes; + remaining_bytes_ -= read_bytes; +} + +void PaintOpReader::Read(PaintFlags* flags) { + // TODO(enne): implement PaintFlags serialization: http://crbug.com/737629 +} + +void PaintOpReader::Read(PaintImage* image) { + // TODO(enne): implement PaintImage serialization: http://crbug.com/737629 +} + +void PaintOpReader::Read(sk_sp<SkData>* data) { + size_t bytes; + ReadSimple(&bytes); + if (remaining_bytes_ < bytes) + valid_ = false; + if (!valid_) + return; + + // Separate out empty vs not valid cases. + if (bytes == 0) { + bool has_data = false; + Read(&has_data); + if (has_data) + *data = SkData::MakeEmpty(); + return; + } + *data = SkData::MakeWithCopy(memory_, bytes); + + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpReader::Read(sk_sp<SkTextBlob>* blob) { + // TODO(enne): implement SkTextBlob serialization: http://crbug.com/737629 +} + +} // namespace cc
diff --git a/cc/paint/paint_op_reader.h b/cc/paint/paint_op_reader.h new file mode 100644 index 0000000..0252178 --- /dev/null +++ b/cc/paint/paint_op_reader.h
@@ -0,0 +1,76 @@ +// 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 CC_PAINT_PAINT_OP_READER_H_ +#define CC_PAINT_PAINT_OP_READER_H_ + +#include <vector> + +#include "cc/paint/paint_op_writer.h" + +namespace cc { + +// PaintOpReader takes garbage |memory| and clobbers it with successive +// read functions. +class PaintOpReader { + public: + PaintOpReader(const void* memory, size_t size) + : memory_(static_cast<const char*>(memory) + + PaintOpWriter::HeaderBytes()), + remaining_bytes_(size - PaintOpWriter::HeaderBytes()) { + if (size < PaintOpWriter::HeaderBytes()) + valid_ = false; + } + + bool valid() const { return valid_; } + + void ReadData(size_t bytes, void* data); + void ReadArray(size_t count, SkPoint* array); + + void Read(SkScalar* data); + void Read(size_t* data); + void Read(uint8_t* data); + void Read(SkRect* rect); + void Read(SkIRect* rect); + void Read(SkRRect* rect); + + void Read(SkPath* path); + void Read(PaintFlags* flags); + void Read(PaintImage* image); + void Read(sk_sp<SkData>* data); + void Read(sk_sp<SkTextBlob>* blob); + + void Read(SkClipOp* op) { + uint8_t value = 0u; + Read(&value); + *op = static_cast<SkClipOp>(value); + } + void Read(PaintCanvas::AnnotationType* type) { + uint8_t value = 0u; + Read(&value); + *type = static_cast<PaintCanvas::AnnotationType>(value); + } + void Read(PaintCanvas::SrcRectConstraint* constraint) { + uint8_t value = 0u; + Read(&value); + *constraint = static_cast<PaintCanvas::SrcRectConstraint>(value); + } + void Read(bool* data) { + uint8_t value = 0u; + Read(&value); + *data = !!value; + } + + private: + template <typename T> + void ReadSimple(T* val); + + const char* memory_ = nullptr; + size_t remaining_bytes_ = 0u; + bool valid_ = true; +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_OP_READER_H_
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc new file mode 100644 index 0000000..1248e17 --- /dev/null +++ b/cc/paint/paint_op_writer.cc
@@ -0,0 +1,104 @@ +// 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 "cc/paint/paint_op_writer.h" + +#include "cc/paint/paint_flags.h" +#include "third_party/skia/include/core/SkTextBlob.h" + +namespace cc { + +template <typename T> +void PaintOpWriter::WriteSimple(const T& val) { + static_assert(base::is_trivially_copyable<T>::value, ""); + if (sizeof(T) > remaining_bytes_) + valid_ = false; + if (!valid_) + return; + + reinterpret_cast<T*>(memory_)[0] = val; + + memory_ += sizeof(T); + remaining_bytes_ -= sizeof(T); +} + +void PaintOpWriter::Write(size_t data) { + WriteSimple(data); +} + +void PaintOpWriter::Write(SkScalar data) { + WriteSimple(data); +} + +void PaintOpWriter::Write(uint8_t data) { + WriteSimple(data); +} + +void PaintOpWriter::Write(const SkRect& rect) { + WriteSimple(rect); +} + +void PaintOpWriter::Write(const SkIRect& rect) { + WriteSimple(rect); +} + +void PaintOpWriter::Write(const SkRRect& rect) { + WriteSimple(rect); +} + +void PaintOpWriter::Write(const SkPath& path) { + size_t bytes = path.writeToMemory(nullptr); + if (bytes > remaining_bytes_) + valid_ = false; + if (!valid_) + return; + + path.writeToMemory(memory_); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpWriter::Write(const PaintFlags& flags) { + // TODO(enne): implement PaintFlags serialization: http://crbug.com/737629 +} + +void PaintOpWriter::Write(const PaintImage& image, ImageDecodeCache* cache) { + // TODO(enne): implement PaintImage serialization: http://crbug.com/737629 +} + +void PaintOpWriter::Write(const sk_sp<SkData>& data) { + if (data.get() && data->size()) { + Write(data->size()); + WriteData(data->size(), data->data()); + } else { + // Differentiate between nullptr and valid but zero size. It's not clear + // that this happens in practice, but seems better to be consistent. + Write(static_cast<size_t>(0)); + Write(!!data.get()); + } +} + +void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { + // TODO(enne): implement SkTextBlob serialization: http://crbug.com/737629 +} + +void PaintOpWriter::WriteData(size_t bytes, const void* input) { + if (bytes > remaining_bytes_) + valid_ = false; + if (!valid_) + return; + if (bytes == 0) + return; + + memcpy(memory_, input, bytes); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpWriter::WriteArray(size_t count, const SkPoint* input) { + size_t bytes = sizeof(SkPoint) * count; + WriteData(bytes, input); +} + +} // namespace cc
diff --git a/cc/paint/paint_op_writer.h b/cc/paint/paint_op_writer.h new file mode 100644 index 0000000..0163067f --- /dev/null +++ b/cc/paint/paint_op_writer.h
@@ -0,0 +1,71 @@ +// 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 CC_PAINT_PAINT_OP_WRITER_H_ +#define CC_PAINT_PAINT_OP_WRITER_H_ + +#include "cc/paint/paint_canvas.h" + +struct SkRect; +struct SkIRect; +class SkRRect; + +namespace cc { + +class ImageDecodeCache; + +class PaintOpWriter { + public: + PaintOpWriter(void* memory, size_t size) + : memory_(static_cast<char*>(memory) + HeaderBytes()), + size_(size), + remaining_bytes_(size - HeaderBytes()) { + // Leave space for header of type/skip. + DCHECK_GE(size, HeaderBytes()); + } + + static size_t constexpr HeaderBytes() { return 4u; } + + // Write a sequence of arbitrary bytes. + void WriteData(size_t bytes, const void* input); + + void WriteArray(size_t count, const SkPoint* input); + + size_t size() const { return valid_ ? size_ - remaining_bytes_ : 0u; } + + void Write(SkScalar data); + void Write(size_t data); + void Write(uint8_t data); + void Write(const SkRect& rect); + void Write(const SkIRect& rect); + void Write(const SkRRect& rect); + + void Write(const SkPath& path); + void Write(const PaintFlags& flags); + void Write(const PaintImage& image, ImageDecodeCache* cache); + void Write(const sk_sp<SkData>& data); + void Write(const sk_sp<SkTextBlob>& blob); + + void Write(SkClipOp op) { Write(static_cast<uint8_t>(op)); } + void Write(PaintCanvas::AnnotationType type) { + Write(static_cast<uint8_t>(type)); + } + void Write(PaintCanvas::SrcRectConstraint constraint) { + Write(static_cast<uint8_t>(constraint)); + } + void Write(bool data) { Write(static_cast<uint8_t>(data)); } + + private: + template <typename T> + void WriteSimple(const T& val); + + char* memory_ = nullptr; + size_t size_ = 0u; + size_t remaining_bytes_ = 0u; + bool valid_ = true; +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_OP_WRITER_H_
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index ad18719..26975dab 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -312,14 +312,11 @@ ResourceProvider::Resource::Resource(Resource&& other) = default; -void ResourceProvider::Resource::set_mailbox(const TextureMailbox& mailbox) { +void ResourceProvider::Resource::SetMailbox(const TextureMailbox& mailbox) { mailbox_ = mailbox; if (IsGpuResourceType(type)) { - // We assume that the mailbox has a valid sync token or else SetLocallyUsed - // must be called after this. synchronization_state_ = - (mailbox.sync_token().HasData() ? NEEDS_WAIT : SYNCHRONIZED); - needs_sync_token_ = false; + mailbox.sync_token().HasData() ? NEEDS_WAIT : SYNCHRONIZED; } else { synchronization_state_ = SYNCHRONIZED; } @@ -328,7 +325,6 @@ void ResourceProvider::Resource::SetLocallyUsed() { synchronization_state_ = LOCALLY_USED; mailbox_.set_sync_token(gpu::SyncToken()); - needs_sync_token_ = IsGpuResourceType(type); } void ResourceProvider::Resource::SetSynchronized() { @@ -337,13 +333,14 @@ void ResourceProvider::Resource::UpdateSyncToken( const gpu::SyncToken& sync_token) { - // In the case of context lost, this sync token may be empty since sync tokens - // may not be generated unless a successful flush occurred. However, we will - // assume the task runner is calling this function properly and update the - // state accordingly. + DCHECK(IsGpuResourceType(type)); + // An empty sync token may be used if commands are guaranteed to have run on + // the gpu process or in case of context loss. mailbox_.set_sync_token(sync_token); - synchronization_state_ = NEEDS_WAIT; - needs_sync_token_ = false; + if (sync_token.HasData()) + synchronization_state_ = NEEDS_WAIT; + else + synchronization_state_ = SYNCHRONIZED; } int8_t* ResourceProvider::Resource::GetSyncTokenData() { @@ -353,10 +350,6 @@ void ResourceProvider::Resource::WaitSyncToken(gpu::gles2::GLES2Interface* gl) { // Make sure we are only called when state actually needs to wait. DCHECK_EQ(NEEDS_WAIT, synchronization_state_); - - // Make sure sync token is not stale. - DCHECK(!needs_sync_token_); - // In the case of context lost, this sync token may be empty (see comment in // the UpdateSyncToken() function). The WaitSyncTokenCHROMIUM() function // handles empty sync tokens properly so just wait anyways and update the @@ -694,7 +687,7 @@ Resource::EXTERNAL, GL_LINEAR)); } resource->allocated = true; - resource->set_mailbox(mailbox); + resource->SetMailbox(mailbox); resource->color_space = mailbox.color_space(); resource->release_callback_impl = base::Bind(&SingleReleaseCallbackImpl::Run, @@ -885,16 +878,14 @@ Resource* resource = GetResource(id); DCHECK(!resource->locked_for_write); DCHECK(!resource->lock_for_read_count); - DCHECK(resource->origin == Resource::INTERNAL); + DCHECK_EQ(resource->origin, Resource::INTERNAL); + DCHECK_NE(resource->synchronization_state(), Resource::NEEDS_WAIT); DCHECK_EQ(resource->exported_count, 0); DCHECK(ReadLockFenceHasPassed(resource)); DCHECK_EQ(image_size.width(), resource->size.width()); DCHECK_EQ(image_size.height(), resource->size.height()); - if (resource->allocated) - WaitSyncTokenIfNeeded(id); - if (resource->type == RESOURCE_TYPE_BITMAP) { DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type); DCHECK(resource->allocated); @@ -907,6 +898,8 @@ SkCanvas dest(lock.sk_bitmap()); dest.writePixels(source_info, image, image_stride, 0, 0); } else { + // No sync token needed because the lock will set synchronization state to + // LOCALLY_USED and a sync token will be generated in PrepareSendToParent. ScopedWriteLockGL lock(this, id, false); unsigned resource_texture_id = lock.texture_id(); DCHECK(resource_texture_id); @@ -924,52 +917,6 @@ image_size.height(), GLDataFormat(resource->format), GLDataType(resource->format), image); } - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gpu::SyncToken sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - lock.set_sync_token(sync_token); - lock.set_synchronized(true); - } -} - -void ResourceProvider::GenerateSyncTokenForResource(ResourceId resource_id) { - Resource* resource = GetResource(resource_id); - if (!resource->needs_sync_token()) - return; - - gpu::SyncToken sync_token; - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - - resource->UpdateSyncToken(sync_token); - resource->SetSynchronized(); -} - -void ResourceProvider::GenerateSyncTokenForResources( - const ResourceIdArray& resource_ids) { - gpu::SyncToken sync_token; - bool created_sync_token = false; - for (ResourceId id : resource_ids) { - Resource* resource = GetResource(id); - if (resource->needs_sync_token()) { - if (!created_sync_token) { - GLES2Interface* gl = ContextGL(); - DCHECK(gl); - - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - created_sync_token = true; - } - - resource->UpdateSyncToken(sync_token); - resource->SetSynchronized(); - } } } @@ -1191,9 +1138,6 @@ DCHECK(thread_checker_.CalledOnValidThread()); Resource* resource = resource_provider_->GetResource(resource_id_); DCHECK(resource->locked_for_write); - // It's not sufficient to check sync_token_.HasData() here because the sync - // might be null because of context loss. Even in that case we want to set the - // sync token because it's checked in PrepareSendToParent while drawing. if (has_sync_token_) resource->UpdateSyncToken(sync_token_); if (synchronized_) @@ -1486,22 +1430,8 @@ // as pointers so we don't have to look up the resource id multiple times. std::vector<Resource*> resources; resources.reserve(resource_ids.size()); - for (const ResourceId id : resource_ids) { - Resource* resource = GetResource(id); - // Check the synchronization and sync token state when delegated sync points - // are required. The only case where we allow a sync token to not be set is - // the case where the image is dirty. In that case we will bind the image - // lazily and generate a sync token at that point. - DCHECK(!settings_.delegated_sync_points_required || resource->dirty_image || - !resource->needs_sync_token()); - - // If we are validating the resource to be sent, the resource cannot be - // in a LOCALLY_USED state. It must have been properly synchronized. - DCHECK(!settings_.delegated_sync_points_required || - Resource::LOCALLY_USED != resource->synchronization_state()); - - resources.push_back(resource); - } + for (const ResourceId id : resource_ids) + resources.push_back(GetResource(id)); // Lazily create any mailboxes and verify all unverified sync tokens. std::vector<GLbyte*> unverified_sync_tokens; @@ -1606,9 +1536,9 @@ TEXTURE_HINT_IMMUTABLE, RESOURCE_TYPE_GL_TEXTURE, it->format)); resource->buffer_format = it->buffer_format; - resource->set_mailbox(TextureMailbox(it->mailbox_holder.mailbox, - it->mailbox_holder.sync_token, - it->mailbox_holder.texture_target)); + resource->SetMailbox(TextureMailbox(it->mailbox_holder.mailbox, + it->mailbox_holder.sync_token, + it->mailbox_holder.texture_target)); resource->read_lock_fences_enabled = it->read_lock_fences_enabled; resource->is_overlay_candidate = it->is_overlay_candidate; #if defined(OS_ANDROID) @@ -1765,7 +1695,7 @@ gl->ProduceTextureDirectCHROMIUM(resource->gl_id, mailbox_holder.texture_target, mailbox_holder.mailbox.name); - resource->set_mailbox(TextureMailbox(mailbox_holder)); + resource->SetMailbox(TextureMailbox(mailbox_holder)); resource->SetLocallyUsed(); }
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index af2f322..6f9a5038 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -168,10 +168,6 @@ const uint8_t* image, const gfx::Size& image_size); - // Generates sync tokesn for resources which need a sync token. - void GenerateSyncTokenForResource(ResourceId resource_id); - void GenerateSyncTokenForResources(const ResourceIdArray& resource_ids); - // Gets the most recent sync token from the indicated resources. gpu::SyncToken GetSyncTokenForResources(const ResourceIdArray& resource_ids); @@ -603,14 +599,17 @@ GLenum filter); Resource(Resource&& other); - bool needs_sync_token() const { return needs_sync_token_; } + bool needs_sync_token() const { + return type != RESOURCE_TYPE_BITMAP && + synchronization_state_ == LOCALLY_USED; + } SynchronizationState synchronization_state() const { return synchronization_state_; } const TextureMailbox& mailbox() const { return mailbox_; } - void set_mailbox(const TextureMailbox& mailbox); + void SetMailbox(const TextureMailbox& mailbox); void SetLocallyUsed(); void SetSynchronized(); @@ -684,7 +683,6 @@ private: SynchronizationState synchronization_state_ = SYNCHRONIZED; - bool needs_sync_token_ = false; TextureMailbox mailbox_; DISALLOW_COPY_AND_ASSIGN(Resource);
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 29468de9..3ba950a 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc
@@ -676,9 +676,6 @@ resource_ids_to_transfer.push_back(id3); resource_ids_to_transfer.push_back(id4); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -938,9 +935,6 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1049,8 +1043,6 @@ resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); std::vector<TransferableResource> list; - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); ASSERT_EQ(3u, list.size()); @@ -1129,9 +1121,6 @@ resource_ids_to_transfer.push_back(ids[i]); } - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1188,9 +1177,6 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1258,9 +1244,6 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1320,9 +1303,6 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1388,9 +1368,6 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1461,9 +1438,6 @@ resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1512,9 +1486,6 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1582,9 +1553,6 @@ resource_ids_to_transfer.push_back(id2); resource_ids_to_transfer.push_back(id3); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1653,7 +1621,6 @@ gfx::ColorSpace()); uint8_t data1[4] = { 1, 2, 3, 4 }; child_resource_provider->CopyToResource(id1, data1, size); - child_resource_provider->GenerateSyncTokenForResource(id1); std::vector<ReturnedResource> returned_to_child; int child_id = @@ -1710,9 +1677,6 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id1); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1770,9 +1734,6 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1807,9 +1768,6 @@ resource_ids_to_transfer.push_back(mapped_id1); resource_ids_to_transfer.push_back(mapped_id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1876,9 +1834,6 @@ resource_ids_to_transfer.push_back(id1); resource_ids_to_transfer.push_back(id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1913,9 +1868,6 @@ resource_ids_to_transfer.push_back(mapped_id1); resource_ids_to_transfer.push_back(mapped_id2); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -1992,9 +1944,6 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -2050,9 +1999,6 @@ ResourceProvider::ResourceIdArray resource_ids_to_transfer; resource_ids_to_transfer.push_back(id); - child_resource_provider_->GenerateSyncTokenForResources( - resource_ids_to_transfer); - std::vector<TransferableResource> list; child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); @@ -2238,8 +2184,6 @@ EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _)); - child_resource_provider->GenerateSyncTokenForResources( - resource_ids_to_transfer); child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list); Mock::VerifyAndClearExpectations(child_context);
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index 2fc54d7..32ac2c6 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -131,6 +131,14 @@ gpu::SyncToken sync_token_; }; +gpu::SyncToken GenerateCompositorSyncToken(gpu::gles2::GLES2Interface* gl) { + gpu::SyncToken sync_token; + const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); + gl->OrderingBarrierCHROMIUM(); + gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + return sync_token; +} + } // namespace VideoResourceUpdater::PlaneResource::PlaneResource( @@ -426,12 +434,15 @@ plane_resource.resource_id()); external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; } else { - // VideoResourceUpdater shares a context with the compositor so - // a sync token is not required. - TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), + // Set the sync token otherwise resource is assumed to be synchronized. + gpu::SyncToken sync_token = + GenerateCompositorSyncToken(context_provider_->ContextGL()); + + TextureMailbox mailbox(plane_resource.mailbox(), sync_token, resource_provider_->GetResourceTextureTarget( plane_resource.resource_id())); mailbox.set_color_space(output_color_space); + external_resources.mailboxes.push_back(mailbox); external_resources.release_callbacks.push_back( base::Bind(&RecycleResource, weak_ptr_factory_.GetWeakPtr(), @@ -529,10 +540,17 @@ resource_size_pixels); plane_resource.SetUniqueId(video_frame->unique_id(), i); } + } + // Set the sync token otherwise resource is assumed to be synchronized. + gpu::SyncToken sync_token = + GenerateCompositorSyncToken(context_provider_->ContextGL()); + + for (size_t i = 0; i < plane_resources.size(); ++i) { + PlaneResource& plane_resource = *plane_resources[i]; // VideoResourceUpdater shares a context with the compositor so a // sync token is not required. - TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), + TextureMailbox mailbox(plane_resource.mailbox(), sync_token, resource_provider_->GetResourceTextureTarget( plane_resource.resource_id())); mailbox.set_color_space(output_color_space); @@ -605,11 +623,10 @@ gl->DeleteTextures(1, &src_texture_id); // Done with the source video frame texture at this point. - video_frame->UpdateReleaseSyncToken(&client); + gpu::SyncToken sync_token = video_frame->UpdateReleaseSyncToken(&client); - // VideoResourceUpdater shares a context with the compositor so a - // sync token is not required. - TextureMailbox mailbox(resource->mailbox(), gpu::SyncToken(), GL_TEXTURE_2D, + // Set sync token otherwise resource is assumed to be synchronized. + TextureMailbox mailbox(resource->mailbox(), sync_token, GL_TEXTURE_2D, video_frame->coded_size(), false, false); mailbox.set_color_space(resource_color_space); external_resources->mailboxes.push_back(mailbox);
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index c00b9fc..576e300 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h
@@ -80,7 +80,6 @@ VideoFrameExternalResources CreateExternalResourcesFromVideoFrame( scoped_refptr<media::VideoFrame> video_frame); - private: class PlaneResource { public:
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc index f27b67f..7d6dfe1 100644 --- a/cc/surfaces/compositor_frame_sink_support.cc +++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -11,9 +11,9 @@ #include "cc/scheduler/begin_frame_source.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" #include "cc/surfaces/display.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_info.h" -#include "cc/surfaces/surface_manager.h" #include "cc/surfaces/surface_reference.h" namespace cc { @@ -21,7 +21,7 @@ // static std::unique_ptr<CompositorFrameSinkSupport> CompositorFrameSinkSupport::Create( CompositorFrameSinkSupportClient* client, - SurfaceManager* surface_manager, + FrameSinkManager* frame_sink_manager, const FrameSinkId& frame_sink_id, bool is_root, bool handles_frame_sink_id_invalidation, @@ -30,7 +30,7 @@ base::WrapUnique(new CompositorFrameSinkSupport( client, frame_sink_id, is_root, handles_frame_sink_id_invalidation, needs_sync_tokens)); - support->Init(surface_manager); + support->Init(frame_sink_manager); return support; } @@ -48,9 +48,9 @@ } EvictCurrentSurface(); - surface_manager_->UnregisterFrameSinkManagerClient(frame_sink_id_); + frame_sink_manager_->UnregisterFrameSinkManagerClient(frame_sink_id_); if (handles_frame_sink_id_invalidation_) - surface_manager_->InvalidateFrameSinkId(frame_sink_id_); + frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_); } void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) { @@ -305,11 +305,12 @@ handles_frame_sink_id_invalidation_(handles_frame_sink_id_invalidation), weak_factory_(this) {} -void CompositorFrameSinkSupport::Init(SurfaceManager* surface_manager) { - surface_manager_ = surface_manager; +void CompositorFrameSinkSupport::Init(FrameSinkManager* frame_sink_manager) { + frame_sink_manager_ = frame_sink_manager; + surface_manager_ = frame_sink_manager->surface_manager(); if (handles_frame_sink_id_invalidation_) - surface_manager_->RegisterFrameSinkId(frame_sink_id_); - surface_manager_->RegisterFrameSinkManagerClient(frame_sink_id_, this); + frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_); + frame_sink_manager_->RegisterFrameSinkManagerClient(frame_sink_id_, this); } void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) { @@ -348,7 +349,7 @@ seen_first_frame_activation_ = false; return surface_manager_->CreateSurface( weak_factory_.GetWeakPtr(), surface_info, - surface_manager_->GetPrimaryBeginFrameSource(), needs_sync_tokens_); + frame_sink_manager_->GetPrimaryBeginFrameSource(), needs_sync_tokens_); } void CompositorFrameSinkSupport::RequestCopyOfSurface(
diff --git a/cc/surfaces/compositor_frame_sink_support.h b/cc/surfaces/compositor_frame_sink_support.h index 6977020..8dffc5b 100644 --- a/cc/surfaces/compositor_frame_sink_support.h +++ b/cc/surfaces/compositor_frame_sink_support.h
@@ -24,6 +24,7 @@ namespace cc { class CompositorFrameSinkSupportClient; +class FrameSinkManager; class Surface; class SurfaceManager; @@ -35,7 +36,7 @@ public: static std::unique_ptr<CompositorFrameSinkSupport> Create( CompositorFrameSinkSupportClient* client, - SurfaceManager* surface_manager, + FrameSinkManager* frame_sink_manager, const FrameSinkId& frame_sink_id, bool is_root, bool handles_frame_sink_id_invalidation, @@ -45,6 +46,7 @@ const FrameSinkId& frame_sink_id() const { return frame_sink_id_; } + FrameSinkManager* frame_sink_manager() { return frame_sink_manager_; } SurfaceManager* surface_manager() { return surface_manager_; } // SurfaceClient implementation. @@ -77,7 +79,7 @@ bool handles_frame_sink_id_invalidation, bool needs_sync_tokens); - void Init(SurfaceManager* surface_manager); + void Init(FrameSinkManager* frame_sink_manager); private: // Updates surface references using |active_referenced_surfaces| from the most @@ -105,6 +107,7 @@ CompositorFrameSinkSupportClient* const client_; + FrameSinkManager* frame_sink_manager_ = nullptr; SurfaceManager* surface_manager_ = nullptr; const FrameSinkId frame_sink_id_;
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc index 7bdf969..38f1681 100644 --- a/cc/surfaces/compositor_frame_sink_support_unittest.cc +++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -11,9 +11,9 @@ #include "cc/resources/resource_provider.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" #include "cc/surfaces/frame_sink_id.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_info.h" -#include "cc/surfaces/surface_manager.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/compositor_frame_helpers.h" #include "cc/test/fake_external_begin_frame_source.h" @@ -106,11 +106,11 @@ local_surface_id_(3, kArbitraryToken), frame_sync_token_(GenTestSyncToken(4)), consumer_sync_token_(GenTestSyncToken(5)) { - manager_.AddObserver(&surface_observer_); + manager_.surface_manager()->AddObserver(&surface_observer_); support_->SetBeginFrameSource(&begin_frame_source_); } ~CompositorFrameSinkSupportTest() override { - manager_.RemoveObserver(&surface_observer_); + manager_.surface_manager()->RemoveObserver(&surface_observer_); support_->EvictCurrentSurface(); } @@ -159,14 +159,18 @@ fake_support_client_.clear_returned_resources(); } + Surface* GetSurfaceForId(const SurfaceId& id) { + return manager_.surface_manager()->GetSurfaceForId(id); + } + void RefCurrentFrameResources() { - Surface* surface = manager_.GetSurfaceForId( + Surface* surface = GetSurfaceForId( SurfaceId(support_->frame_sink_id(), local_surface_id_)); support_->RefResources(surface->GetActiveFrame().resource_list); } protected: - SurfaceManager manager_; + FrameSinkManager manager_; FakeCompositorFrameSinkSupportClient fake_support_client_; std::unique_ptr<CompositorFrameSinkSupport> support_; FakeExternalBeginFrameSource begin_frame_source_; @@ -522,11 +526,11 @@ std::vector<ReturnedResource> returned_resources = { resource.ToReturnedResource()}; - EXPECT_TRUE(manager_.GetSurfaceForId(id)); + EXPECT_TRUE(GetSurfaceForId(id)); EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources)) .Times(1); support->EvictCurrentSurface(); - EXPECT_FALSE(manager_.GetSurfaceForId(id)); + EXPECT_FALSE(GetSurfaceForId(id)); } // Tests doing an EvictCurrentSurface which has unregistered dependency. @@ -550,18 +554,18 @@ local_surface_id_ = LocalSurfaceId(); SurfaceId surface_id(kAnotherArbitraryFrameSinkId, local_surface_id); - Surface* surface = manager_.GetSurfaceForId(surface_id); + Surface* surface = GetSurfaceForId(surface_id); surface->AddDestructionDependency( SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); std::vector<ReturnedResource> returned_resource = { resource.ToReturnedResource()}; - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); + EXPECT_TRUE(GetSurfaceForId(surface_id)); EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resource)) .Times(1); support->EvictCurrentSurface(); - EXPECT_FALSE(manager_.GetSurfaceForId(surface_id)); + EXPECT_FALSE(GetSurfaceForId(surface_id)); } // Tests doing an EvictCurrentSurface which has registered dependency. @@ -588,21 +592,22 @@ manager_.RegisterFrameSinkId(kYetAnotherArbitraryFrameSinkId); SurfaceId surface_id(kAnotherArbitraryFrameSinkId, local_surface_id); - Surface* surface = manager_.GetSurfaceForId(surface_id); + Surface* surface = GetSurfaceForId(surface_id); surface->AddDestructionDependency( SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); std::vector<ReturnedResource> returned_resources; - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); + EXPECT_TRUE(GetSurfaceForId(surface_id)); support->EvictCurrentSurface(); - EXPECT_TRUE(manager_.GetSurfaceForId(surface_id)); + EXPECT_TRUE(GetSurfaceForId(surface_id)); EXPECT_EQ(0u, execute_count); returned_resources.push_back(resource.ToReturnedResource()); EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources)) .Times(1); - manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); - EXPECT_FALSE(manager_.GetSurfaceForId(surface_id)); + manager_.surface_manager()->SatisfySequence( + SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); + EXPECT_FALSE(GetSurfaceForId(surface_id)); } TEST_F(CompositorFrameSinkSupportTest, DestroySequence) { @@ -615,22 +620,24 @@ support2->SubmitCompositorFrame(local_surface_id2, MakeCompositorFrame()); // Check that waiting before the sequence is satisfied works. - manager_.GetSurfaceForId(id2)->AddDestructionDependency( + GetSurfaceForId(id2)->AddDestructionDependency( SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); support2->EvictCurrentSurface(); - DCHECK(manager_.GetSurfaceForId(id2)); - manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); - manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 6)); - DCHECK(!manager_.GetSurfaceForId(id2)); + DCHECK(GetSurfaceForId(id2)); + manager_.surface_manager()->SatisfySequence( + SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4)); + manager_.surface_manager()->SatisfySequence( + SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 6)); + DCHECK(!GetSurfaceForId(id2)); // Check that waiting after the sequence is satisfied works. support2->SubmitCompositorFrame(local_surface_id2, MakeCompositorFrame()); - DCHECK(manager_.GetSurfaceForId(id2)); - manager_.GetSurfaceForId(id2)->AddDestructionDependency( + DCHECK(GetSurfaceForId(id2)); + GetSurfaceForId(id2)->AddDestructionDependency( SurfaceSequence(kAnotherArbitraryFrameSinkId, 6)); support2->EvictCurrentSurface(); - DCHECK(!manager_.GetSurfaceForId(id2)); + DCHECK(!GetSurfaceForId(id2)); } // Tests that Surface ID namespace invalidation correctly allows @@ -643,19 +650,19 @@ support_->SubmitCompositorFrame(local_surface_id, MakeCompositorFrame()); manager_.RegisterFrameSinkId(frame_sink_id); - manager_.GetSurfaceForId(id)->AddDestructionDependency( + GetSurfaceForId(id)->AddDestructionDependency( SurfaceSequence(frame_sink_id, 4)); support_->EvictCurrentSurface(); // Verify the dependency has prevented the surface from getting destroyed. - EXPECT_TRUE(manager_.GetSurfaceForId(id)); + EXPECT_TRUE(GetSurfaceForId(id)); manager_.InvalidateFrameSinkId(frame_sink_id); // Verify that the invalidated namespace caused the unsatisfied sequence // to be ignored. - EXPECT_FALSE(manager_.GetSurfaceForId(id)); + EXPECT_FALSE(GetSurfaceForId(id)); } TEST_F(CompositorFrameSinkSupportTest, DestroyCycle) { @@ -681,7 +688,7 @@ EXPECT_EQ(surface_observer_.last_created_surface_id().local_surface_id(), local_surface_id2); } - manager_.GetSurfaceForId(id2)->AddDestructionDependency( + GetSurfaceForId(id2)->AddDestructionDependency( SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); support2->EvictCurrentSurface(); // Give local_surface_id_ a frame that references id2. @@ -691,18 +698,19 @@ support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)); } support_->EvictCurrentSurface(); - EXPECT_TRUE(manager_.GetSurfaceForId(id2)); + EXPECT_TRUE(GetSurfaceForId(id2)); // local_surface_id_ should be retained by reference from id2. - EXPECT_TRUE(manager_.GetSurfaceForId( - SurfaceId(support_->frame_sink_id(), local_surface_id_))); + EXPECT_TRUE( + GetSurfaceForId(SurfaceId(support_->frame_sink_id(), local_surface_id_))); // Satisfy last destruction dependency for id2. - manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); + manager_.surface_manager()->SatisfySequence( + SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); // id2 and local_surface_id_ are in a reference cycle that has no surface // sequences holding on to it, so they should be destroyed. - EXPECT_TRUE(!manager_.GetSurfaceForId(id2)); - EXPECT_TRUE(!manager_.GetSurfaceForId( + EXPECT_TRUE(!GetSurfaceForId(id2)); + EXPECT_TRUE(!GetSurfaceForId( SurfaceId(support_->frame_sink_id(), local_surface_id_))); local_surface_id_ = LocalSurfaceId(); @@ -791,7 +799,7 @@ frame.render_pass_list.push_back(RenderPass::Create()); EXPECT_TRUE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); - EXPECT_FALSE(manager_.GetSurfaceForId(id)); + EXPECT_FALSE(GetSurfaceForId(id)); } // Check that if a CompositorFrame is received with device scale factor of 0, we @@ -802,7 +810,7 @@ frame.metadata.device_scale_factor = 0.f; EXPECT_TRUE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); - EXPECT_FALSE(manager_.GetSurfaceForId(id)); + EXPECT_FALSE(GetSurfaceForId(id)); } // Check that if the size of a CompositorFrame doesn't match the size of the @@ -817,7 +825,7 @@ frame.render_pass_list.push_back(std::move(pass)); EXPECT_TRUE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); - EXPECT_TRUE(manager_.GetSurfaceForId(id)); + EXPECT_TRUE(GetSurfaceForId(id)); // Submit a frame with size (5,4). This frame should be rejected and the // surface should be destroyed. @@ -827,7 +835,7 @@ frame.render_pass_list.push_back(std::move(pass)); EXPECT_FALSE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); - EXPECT_FALSE(manager_.GetSurfaceForId(id)); + EXPECT_FALSE(GetSurfaceForId(id)); } // Check that if the device scale factor of a CompositorFrame doesn't match the @@ -841,7 +849,7 @@ frame.metadata.device_scale_factor = 0.5f; EXPECT_TRUE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); - EXPECT_TRUE(manager_.GetSurfaceForId(id)); + EXPECT_TRUE(GetSurfaceForId(id)); // Submit a frame with device scale factor of 0.4. This frame should be // rejected and the surface should be destroyed. @@ -849,7 +857,7 @@ frame.metadata.device_scale_factor = 0.4f; EXPECT_FALSE( support_->SubmitCompositorFrame(local_surface_id_, std::move(frame))); - EXPECT_FALSE(manager_.GetSurfaceForId(id)); + EXPECT_FALSE(GetSurfaceForId(id)); } TEST_F(CompositorFrameSinkSupportTest, PassesOnBeginFrameAcks) {
diff --git a/cc/surfaces/direct_layer_tree_frame_sink.cc b/cc/surfaces/direct_layer_tree_frame_sink.cc index 8a3bee4..1b57532 100644 --- a/cc/surfaces/direct_layer_tree_frame_sink.cc +++ b/cc/surfaces/direct_layer_tree_frame_sink.cc
@@ -9,15 +9,15 @@ #include "cc/output/layer_tree_frame_sink_client.h" #include "cc/surfaces/display.h" #include "cc/surfaces/frame_sink_id.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" -#include "cc/surfaces/surface_manager.h" namespace cc { DirectLayerTreeFrameSink::DirectLayerTreeFrameSink( const FrameSinkId& frame_sink_id, - SurfaceManager* surface_manager, + FrameSinkManager* frame_sink_manager, Display* display, scoped_refptr<ContextProvider> context_provider, scoped_refptr<ContextProvider> worker_context_provider, @@ -28,7 +28,7 @@ gpu_memory_buffer_manager, shared_bitmap_manager), frame_sink_id_(frame_sink_id), - surface_manager_(surface_manager), + frame_sink_manager_(frame_sink_manager), display_(display) { DCHECK(thread_checker_.CalledOnValidThread()); capabilities_.must_always_swap = true; @@ -39,12 +39,12 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink( const FrameSinkId& frame_sink_id, - SurfaceManager* surface_manager, + FrameSinkManager* frame_sink_manager, Display* display, scoped_refptr<VulkanContextProvider> vulkan_context_provider) : LayerTreeFrameSink(std::move(vulkan_context_provider)), frame_sink_id_(frame_sink_id), - surface_manager_(surface_manager), + frame_sink_manager_(frame_sink_manager), display_(display) { DCHECK(thread_checker_.CalledOnValidThread()); capabilities_.must_always_swap = true; @@ -69,7 +69,7 @@ constexpr bool is_root = true; constexpr bool handles_frame_sink_id_invalidation = false; support_ = CompositorFrameSinkSupport::Create( - this, surface_manager_, frame_sink_id_, is_root, + this, frame_sink_manager_, frame_sink_id_, is_root, handles_frame_sink_id_invalidation, capabilities_.delegated_sync_points_required); begin_frame_source_ = base::MakeUnique<ExternalBeginFrameSource>(this); @@ -77,7 +77,7 @@ // Avoid initializing GL context here, as this should be sharing the // Display's context. - display_->Initialize(this, surface_manager_); + display_->Initialize(this, frame_sink_manager_->surface_manager()); return true; }
diff --git a/cc/surfaces/direct_layer_tree_frame_sink.h b/cc/surfaces/direct_layer_tree_frame_sink.h index 303357e..b1bcaf5 100644 --- a/cc/surfaces/direct_layer_tree_frame_sink.h +++ b/cc/surfaces/direct_layer_tree_frame_sink.h
@@ -18,7 +18,7 @@ namespace cc { class Display; class LocalSurfaceIdAllocator; -class SurfaceManager; +class FrameSinkManager; // This class submits compositor frames to an in-process Display, with the // client's frame being the root surface of the Display. @@ -28,11 +28,11 @@ public ExternalBeginFrameSourceClient, public NON_EXPORTED_BASE(DisplayClient) { public: - // The underlying Display, SurfaceManager, and LocalSurfaceIdAllocator must + // The underlying Display, FrameSinkManager, and LocalSurfaceIdAllocator must // outlive this class. DirectLayerTreeFrameSink( const FrameSinkId& frame_sink_id, - SurfaceManager* surface_manager, + FrameSinkManager* frame_sink_manager, Display* display, scoped_refptr<ContextProvider> context_provider, scoped_refptr<ContextProvider> worker_context_provider, @@ -40,7 +40,7 @@ SharedBitmapManager* shared_bitmap_manager); DirectLayerTreeFrameSink( const FrameSinkId& frame_sink_id, - SurfaceManager* surface_manager, + FrameSinkManager* frame_sink_manager, Display* display, scoped_refptr<VulkanContextProvider> vulkan_context_provider); ~DirectLayerTreeFrameSink() override; @@ -78,7 +78,7 @@ const FrameSinkId frame_sink_id_; LocalSurfaceId local_surface_id_; - SurfaceManager* surface_manager_; + FrameSinkManager* frame_sink_manager_; LocalSurfaceIdAllocator local_surface_id_allocator_; Display* display_; gfx::Size last_swap_frame_size_;
diff --git a/cc/surfaces/direct_layer_tree_frame_sink_unittest.cc b/cc/surfaces/direct_layer_tree_frame_sink_unittest.cc index 3558826..d1acb3da 100644 --- a/cc/surfaces/direct_layer_tree_frame_sink_unittest.cc +++ b/cc/surfaces/direct_layer_tree_frame_sink_unittest.cc
@@ -14,8 +14,8 @@ #include "cc/surfaces/display.h" #include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/frame_sink_id.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/compositor_frame_helpers.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" @@ -46,7 +46,7 @@ display_size_(1920, 1080), display_rect_(display_size_), context_provider_(TestContextProvider::Create()) { - surface_manager_.RegisterFrameSinkId(kArbitraryFrameSinkId); + frame_sink_manager_.RegisterFrameSinkId(kArbitraryFrameSinkId); std::unique_ptr<FakeOutputSurface> display_output_surface = FakeOutputSurface::Create3d(); @@ -65,7 +65,7 @@ std::move(scheduler), base::MakeUnique<TextureMailboxDeleter>(task_runner_.get()))); layer_tree_frame_sink_.reset(new TestDirectLayerTreeFrameSink( - kArbitraryFrameSinkId, &surface_manager_, display_.get(), + kArbitraryFrameSinkId, &frame_sink_manager_, display_.get(), context_provider_, nullptr, &gpu_memory_buffer_manager_, &bitmap_manager_)); @@ -107,7 +107,7 @@ const gfx::Size display_size_; const gfx::Rect display_rect_; - SurfaceManager surface_manager_; + FrameSinkManager frame_sink_manager_; TestSharedBitmapManager bitmap_manager_; TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
diff --git a/cc/surfaces/display_unittest.cc b/cc/surfaces/display_unittest.cc index 5b16888ce..5abeff7 100644 --- a/cc/surfaces/display_unittest.cc +++ b/cc/surfaces/display_unittest.cc
@@ -18,6 +18,7 @@ #include "cc/surfaces/display_client.h" #include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/frame_sink_id.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_manager.h" @@ -153,7 +154,7 @@ support_->SubmitCompositorFrame(local_surface_id, std::move(frame)); } - SurfaceManager manager_; + FrameSinkManager manager_; std::unique_ptr<CompositorFrameSinkSupport> support_; LocalSurfaceIdAllocator id_allocator_; scoped_refptr<base::NullTaskRunner> task_runner_; @@ -187,7 +188,7 @@ gfx::ColorSpace color_space_2 = gfx::ColorSpace::CreateSCRGBLinear(); StubDisplayClient client; - display_->Initialize(&client, &manager_); + display_->Initialize(&client, manager_.surface_manager()); display_->SetColorSpace(color_space_1, color_space_1); LocalSurfaceId local_surface_id(id_allocator_.GenerateId()); @@ -445,7 +446,7 @@ gfx::ColorSpace color_space_2 = gfx::ColorSpace::CreateSCRGBLinear(); StubDisplayClient client; - display_->Initialize(&client, &manager_); + display_->Initialize(&client, manager_.surface_manager()); display_->SetColorSpace(color_space_1, color_space_1); LocalSurfaceId local_surface_id(id_allocator_.GenerateId()); @@ -514,7 +515,7 @@ SetUpDisplay(settings, std::move(context)); StubDisplayClient client; - display_->Initialize(&client, &manager_); + display_->Initialize(&client, manager_.surface_manager()); display_->SetLocalSurfaceId(local_surface_id1, 1.f); @@ -584,7 +585,7 @@ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create()); CountLossDisplayClient client; - display_->Initialize(&client, &manager_); + display_->Initialize(&client, manager_.surface_manager()); // Verify DidLoseOutputSurface callback is hooked up correctly. EXPECT_EQ(0, client.loss_count()); @@ -605,7 +606,7 @@ // Set up first display. SetUpDisplay(settings, nullptr); StubDisplayClient client; - display_->Initialize(&client, &manager_); + display_->Initialize(&client, manager_.surface_manager()); display_->SetLocalSurfaceId(local_surface_id, 1.f); // Set up second frame sink + display. @@ -624,7 +625,7 @@ manager_.RegisterBeginFrameSource(begin_frame_source2.get(), kAnotherFrameSinkId); StubDisplayClient client2; - display2->Initialize(&client2, &manager_); + display2->Initialize(&client2, manager_.surface_manager()); display2->SetLocalSurfaceId(local_surface_id, 1.f); display_->Resize(gfx::Size(100, 100));
diff --git a/cc/surfaces/frame_sink_manager.cc b/cc/surfaces/frame_sink_manager.cc index 2d6078a..5265448 100644 --- a/cc/surfaces/frame_sink_manager.cc +++ b/cc/surfaces/frame_sink_manager.cc
@@ -8,6 +8,7 @@ #include <stdint.h> #include "base/logging.h" +#include "cc/surfaces/display.h" #include "cc/surfaces/frame_sink_manager_client.h" #include "cc/surfaces/primary_begin_frame_source.h" @@ -24,7 +25,8 @@ FrameSinkManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() = default; -FrameSinkManager::FrameSinkManager() = default; +FrameSinkManager::FrameSinkManager(SurfaceManager::LifetimeType lifetime_type) + : surface_manager_(lifetime_type) {} FrameSinkManager::~FrameSinkManager() { // All FrameSinks should be unregistered prior to SurfaceManager destruction. @@ -33,19 +35,18 @@ } void FrameSinkManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { - bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; - DCHECK(inserted); + surface_manager_.RegisterFrameSinkId(frame_sink_id); } void FrameSinkManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { - valid_frame_sink_ids_.erase(frame_sink_id); + surface_manager_.InvalidateFrameSinkId(frame_sink_id); } void FrameSinkManager::RegisterFrameSinkManagerClient( const FrameSinkId& frame_sink_id, FrameSinkManagerClient* client) { DCHECK(client); - DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); + DCHECK_EQ(surface_manager_.GetValidFrameSinkIds().count(frame_sink_id), 1u); clients_[frame_sink_id] = client; @@ -58,7 +59,7 @@ void FrameSinkManager::UnregisterFrameSinkManagerClient( const FrameSinkId& frame_sink_id) { - DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); + DCHECK_EQ(surface_manager_.GetValidFrameSinkIds().count(frame_sink_id), 1u); auto client_iter = clients_.find(frame_sink_id); DCHECK(client_iter != clients_.end()); @@ -77,7 +78,7 @@ const FrameSinkId& frame_sink_id) { DCHECK(source); DCHECK_EQ(registered_sources_.count(source), 0u); - DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); + DCHECK_EQ(surface_manager_.GetValidFrameSinkIds().count(frame_sink_id), 1u); registered_sources_[source] = frame_sink_id; RecursivelyAttachBeginFrameSource(frame_sink_id, source); @@ -120,8 +121,14 @@ if (client_iter != clients_.end()) client_iter->second->SetBeginFrameSource(source); } - for (size_t i = 0; i < mapping.children.size(); ++i) - RecursivelyAttachBeginFrameSource(mapping.children[i], source); + for (size_t i = 0; i < mapping.children.size(); ++i) { + // |frame_sink_source_map_| is a container that can allocate new memory and + // move data between buffers. Copy child's FrameSinkId before passing it to + // RecursivelyAttachBeginFrameSource so that we don't reference data inside + // |frame_sink_source_map_|. + FrameSinkId child_copy = mapping.children[i]; + RecursivelyAttachBeginFrameSource(child_copy, source); + } } void FrameSinkManager::RecursivelyDetachBeginFrameSource( @@ -234,4 +241,8 @@ RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); } +void FrameSinkManager::DropTemporaryReference(const SurfaceId& surface_id) { + surface_manager_.DropTemporaryReference(surface_id); +} + } // namespace cc
diff --git a/cc/surfaces/frame_sink_manager.h b/cc/surfaces/frame_sink_manager.h index 11c0f97..2833389 100644 --- a/cc/surfaces/frame_sink_manager.h +++ b/cc/surfaces/frame_sink_manager.h
@@ -8,13 +8,14 @@ #include <stdint.h> #include <unordered_map> -#include <unordered_set> #include <vector> +#include "base/containers/flat_map.h" #include "base/logging.h" #include "base/macros.h" #include "cc/surfaces/frame_sink_id.h" #include "cc/surfaces/primary_begin_frame_source.h" +#include "cc/surfaces/surface_manager.h" #include "cc/surfaces/surfaces_export.h" namespace cc { @@ -22,12 +23,17 @@ class FrameSinkManagerClient; namespace test { +class CompositorFrameSinkSupportTest; class SurfaceSynchronizationTest; } +// FrameSinkManager manages BeginFrame hierarchy. This is the implementation +// detail for FrameSinkManagerImpl. +// TODO(staraz): Merge FrameSinkManager into FrameSinkManagerImpl. class CC_SURFACES_EXPORT FrameSinkManager { public: - FrameSinkManager(); + explicit FrameSinkManager(SurfaceManager::LifetimeType lifetime_type = + SurfaceManager::LifetimeType::SEQUENCES); ~FrameSinkManager(); void RegisterFrameSinkId(const FrameSinkId& frame_sink_id); @@ -71,13 +77,15 @@ void UnregisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, const FrameSinkId& child_frame_sink_id); - // Export list of valid frame_sink_ids for SatisfyDestructionDeps in surface - // may be removed later when References replace Sequences - std::unordered_set<FrameSinkId, FrameSinkIdHash>* GetValidFrameSinkIds() { - return &valid_frame_sink_ids_; - } + // Drops the temporary reference for |surface_id|. If a surface reference has + // already been added from the parent to |surface_id| then this will do + // nothing. + void DropTemporaryReference(const SurfaceId& surface_id); + + SurfaceManager* surface_manager() { return &surface_manager_; } private: + friend class test::CompositorFrameSinkSupportTest; friend class test::SurfaceSynchronizationTest; void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id, @@ -90,11 +98,6 @@ bool ChildContains(const FrameSinkId& child_frame_sink_id, const FrameSinkId& search_frame_sink_id) const; - // Set of valid framesink Ids. When a framesink Id is removed from - // this set, any remaining (surface) sequences with that framesink are - // considered satisfied. - std::unordered_set<FrameSinkId, FrameSinkIdHash> valid_frame_sink_ids_; - // Begin frame source routing. Both BeginFrameSource and // CompositorFrameSinkSupport pointers guaranteed alive by callers until // unregistered. @@ -109,9 +112,7 @@ std::vector<FrameSinkId> children; }; - std::unordered_map<FrameSinkId, FrameSinkManagerClient*, FrameSinkIdHash> - clients_; - + base::flat_map<FrameSinkId, FrameSinkManagerClient*> clients_; std::unordered_map<FrameSinkId, FrameSinkSourceMapping, FrameSinkIdHash> frame_sink_source_map_; @@ -122,6 +123,10 @@ PrimaryBeginFrameSource primary_source_; + // |surface_manager_| should be placed under |primary_source_| so that all + // surfaces are destroyed before |primary_source_|. + SurfaceManager surface_manager_; + DISALLOW_COPY_AND_ASSIGN(FrameSinkManager); };
diff --git a/cc/surfaces/surface_manager_unittest.cc b/cc/surfaces/frame_sink_manager_unittest.cc similarity index 96% rename from cc/surfaces/surface_manager_unittest.cc rename to cc/surfaces/frame_sink_manager_unittest.cc index 4dbce5d..8cd721f4 100644 --- a/cc/surfaces/surface_manager_unittest.cc +++ b/cc/surfaces/frame_sink_manager_unittest.cc
@@ -5,8 +5,8 @@ #include <stddef.h> #include "cc/scheduler/begin_frame_source.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/frame_sink_manager_client.h" -#include "cc/surfaces/surface_manager.h" #include "cc/test/begin_frame_source_test.h" #include "cc/test/fake_external_begin_frame_source.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,7 +19,7 @@ : source_(nullptr), manager_(nullptr), frame_sink_id_(frame_sink_id) {} FakeFrameSinkManagerClient(const FrameSinkId& frame_sink_id, - SurfaceManager* manager) + FrameSinkManager* manager) : source_(nullptr), manager_(nullptr), frame_sink_id_(frame_sink_id) { DCHECK(manager); Register(manager); @@ -35,7 +35,7 @@ BeginFrameSource* source() { return source_; } const FrameSinkId& frame_sink_id() { return frame_sink_id_; } - void Register(SurfaceManager* manager) { + void Register(FrameSinkManager* manager) { EXPECT_EQ(nullptr, manager_); manager_ = manager; manager_->RegisterFrameSinkManagerClient(frame_sink_id_, this); @@ -55,32 +55,32 @@ private: BeginFrameSource* source_; - SurfaceManager* manager_; + FrameSinkManager* manager_; FrameSinkId frame_sink_id_; }; -class SurfaceManagerTest : public testing::Test { +class FrameSinkManagerTest : public testing::Test { public: // These tests don't care about namespace registration, so just preregister // a set of namespaces that tests can use freely without worrying if they're // valid or not. enum { MAX_FRAME_SINK = 10 }; - SurfaceManagerTest() { + FrameSinkManagerTest() { for (size_t i = 0; i < MAX_FRAME_SINK; ++i) manager_.RegisterFrameSinkId(FrameSinkId(i, i)); } - ~SurfaceManagerTest() override { + ~FrameSinkManagerTest() override { for (size_t i = 0; i < MAX_FRAME_SINK; ++i) manager_.InvalidateFrameSinkId(FrameSinkId(i, i)); } protected: - SurfaceManager manager_; + FrameSinkManager manager_; }; -TEST_F(SurfaceManagerTest, SingleClients) { +TEST_F(FrameSinkManagerTest, SingleClients) { FakeFrameSinkManagerClient client(FrameSinkId(1, 1)); FakeFrameSinkManagerClient other_client(FrameSinkId(2, 2)); StubBeginFrameSource source; @@ -118,7 +118,7 @@ // This test verifies that a PrimaryBeginFrameSource will receive BeginFrames // from the first BeginFrameSource registered. If that BeginFrameSource goes // away then it will receive BeginFrames from the second BeginFrameSource. -TEST_F(SurfaceManagerTest, PrimaryBeginFrameSource) { +TEST_F(FrameSinkManagerTest, PrimaryBeginFrameSource) { // This PrimaryBeginFrameSource should track the first BeginFrameSource // registered with the SurfaceManager. testing::NiceMock<MockBeginFrameObserver> obs; @@ -174,7 +174,7 @@ begin_frame_source->RemoveObserver(&obs); } -TEST_F(SurfaceManagerTest, MultipleDisplays) { +TEST_F(FrameSinkManagerTest, MultipleDisplays) { StubBeginFrameSource root1_source; StubBeginFrameSource root2_source; @@ -244,7 +244,7 @@ // This test verifies that a BeginFrameSource path to the root from a // FrameSinkId is preserved even if that FrameSinkId has no children // and does not have a corresponding FrameSinkManagerClient. -TEST_F(SurfaceManagerTest, ParentWithoutClientRetained) { +TEST_F(FrameSinkManagerTest, ParentWithoutClientRetained) { StubBeginFrameSource root_source; constexpr FrameSinkId kFrameSinkIdRoot(1, 1); @@ -282,7 +282,7 @@ // However, this unit test registers the BeginFrameSource AFTER C // has been attached to A. This test verifies that the BeginFrameSource // propagates all the way to C. -TEST_F(SurfaceManagerTest, +TEST_F(FrameSinkManagerTest, ParentWithoutClientRetained_LateBeginFrameRegistration) { StubBeginFrameSource root_source; @@ -324,7 +324,7 @@ // are properly set up and cleaned up under the four permutations of orderings // of this nesting. -class SurfaceManagerOrderingTest : public SurfaceManagerTest { +class SurfaceManagerOrderingTest : public FrameSinkManagerTest { public: SurfaceManagerOrderingTest() : client_a_(FrameSinkId(1, 1)),
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index 99e479d..c578ef2 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -360,8 +360,8 @@ } void Surface::SatisfyDestructionDependencies( - std::unordered_set<SurfaceSequence, SurfaceSequenceHash>* sequences, - std::unordered_set<FrameSinkId, FrameSinkIdHash>* valid_frame_sink_ids) { + base::flat_set<SurfaceSequence>* sequences, + base::flat_set<FrameSinkId>* valid_frame_sink_ids) { base::EraseIf(destruction_dependencies_, [sequences, valid_frame_sink_ids](SurfaceSequence seq) { return (!!sequences->erase(seq) ||
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index 8b9be1b9..660a6ecd 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h
@@ -124,8 +124,8 @@ // Satisfy all destruction dependencies that are contained in sequences, and // remove them from sequences. void SatisfyDestructionDependencies( - std::unordered_set<SurfaceSequence, SurfaceSequenceHash>* sequences, - std::unordered_set<FrameSinkId, FrameSinkIdHash>* valid_id_namespaces); + base::flat_set<SurfaceSequence>* sequences, + base::flat_set<FrameSinkId>* valid_id_namespaces); size_t GetDestructionDependencyCount() const { return destruction_dependencies_.size(); }
diff --git a/cc/surfaces/surface_aggregator_perftest.cc b/cc/surfaces/surface_aggregator_perftest.cc index ac7fb4b5..89ef0f9 100644 --- a/cc/surfaces/surface_aggregator_perftest.cc +++ b/cc/surfaces/surface_aggregator_perftest.cc
@@ -8,6 +8,7 @@ #include "cc/quads/surface_draw_quad.h" #include "cc/quads/texture_draw_quad.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface_aggregator.h" #include "cc/surfaces/surface_manager.h" #include "cc/test/compositor_frame_helpers.h" @@ -52,8 +53,8 @@ nullptr, &manager_, FrameSinkId(1, i + 1), kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); } - aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(), - optimize_damage)); + aggregator_.reset(new SurfaceAggregator( + manager_.surface_manager(), resource_provider_.get(), optimize_damage)); for (int i = 0; i < num_surfaces; i++) { LocalSurfaceId local_surface_id(i + 1, kArbitraryToken); @@ -149,7 +150,7 @@ } protected: - SurfaceManager manager_; + FrameSinkManager manager_; scoped_refptr<TestContextProvider> context_provider_; std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_; std::unique_ptr<ResourceProvider> resource_provider_;
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index 38af83b..fe1130fd 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -19,6 +19,7 @@ #include "cc/quads/texture_draw_quad.h" #include "cc/resources/shared_bitmap_manager.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_manager.h" @@ -70,8 +71,8 @@ kRootIsRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)), - aggregator_(&manager_, NULL, use_damage_rect) { - manager_.AddObserver(&observer_); + aggregator_(manager_.surface_manager(), NULL, use_damage_rect) { + manager_.surface_manager()->AddObserver(&observer_); } SurfaceAggregatorTest() : SurfaceAggregatorTest(false) {} @@ -83,7 +84,7 @@ } protected: - SurfaceManager manager_; + FrameSinkManager manager_; FakeSurfaceObserver observer_; FakeCompositorFrameSinkSupportClient fake_client_; std::unique_ptr<CompositorFrameSinkSupport> support_; @@ -107,7 +108,7 @@ void SetUp() override { SurfaceAggregatorTest::SetUp(); root_local_surface_id_ = allocator_.GenerateId(); - root_surface_ = manager_.GetSurfaceForId( + root_surface_ = manager_.surface_manager()->GetSurfaceForId( SurfaceId(support_->frame_sink_id(), root_local_surface_id_)); } @@ -634,8 +635,9 @@ } // Ensure copy requests have been removed from root surface. - const CompositorFrame& original_frame = - manager_.GetSurfaceForId(root_surface_id)->GetActiveFrame(); + const CompositorFrame& original_frame = manager_.surface_manager() + ->GetSurfaceForId(root_surface_id) + ->GetActiveFrame(); const RenderPassList& original_pass_list = original_frame.render_pass_list; ASSERT_EQ(2u, original_pass_list.size()); DCHECK(original_pass_list[0]->copy_requests.empty()); @@ -1954,13 +1956,13 @@ resource_provider_ = FakeResourceProvider::Create(nullptr, shared_bitmap_manager_.get()); - aggregator_.reset( - new SurfaceAggregator(&manager_, resource_provider_.get(), false)); + aggregator_.reset(new SurfaceAggregator(manager_.surface_manager(), + resource_provider_.get(), false)); aggregator_->set_output_is_secure(true); } protected: - SurfaceManager manager_; + FrameSinkManager manager_; std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_; std::unique_ptr<ResourceProvider> resource_provider_; std::unique_ptr<SurfaceAggregator> aggregator_;
diff --git a/cc/surfaces/surface_hittest_unittest.cc b/cc/surfaces/surface_hittest_unittest.cc index 9b2b236..386e069 100644 --- a/cc/surfaces/surface_hittest_unittest.cc +++ b/cc/surfaces/surface_hittest_unittest.cc
@@ -6,6 +6,7 @@ #include "cc/output/compositor_frame.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_hittest.h" @@ -65,7 +66,7 @@ // This test verifies that hit testing on a surface that does not exist does // not crash. TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) { - SurfaceManager manager; + FrameSinkManager manager; FrameSinkId root_frame_sink_id(kArbitraryFrameSinkId); std::unique_ptr<CompositorFrameSinkSupport> root_support = CompositorFrameSinkSupport::Create( @@ -96,7 +97,7 @@ std::move(root_frame)); { - SurfaceHittest hittest(nullptr, &manager); + SurfaceHittest hittest(nullptr, manager.surface_manager()); // It is expected this test will complete without crashes. gfx::Transform transform; EXPECT_EQ(root_surface_id, @@ -108,7 +109,7 @@ } TEST(SurfaceHittestTest, Hittest_SingleSurface) { - SurfaceManager manager; + FrameSinkManager manager; // Set up root FrameSink. FrameSinkId root_frame_sink_id(1, 1); @@ -137,13 +138,13 @@ }, }; - RunTests(nullptr, &manager, tests, arraysize(tests)); + RunTests(nullptr, manager.surface_manager(), tests, arraysize(tests)); root_support->EvictCurrentSurface(); } TEST(SurfaceHittestTest, Hittest_ChildSurface) { - SurfaceManager manager; + FrameSinkManager manager; // Set up root FrameSink. FrameSinkId root_frame_sink_id(1, 1); @@ -242,7 +243,7 @@ } }; - RunTests(nullptr, &manager, tests, arraysize(tests)); + RunTests(nullptr, manager.surface_manager(), tests, arraysize(tests)); // Submit another root frame, with a slightly perturbed child Surface. root_frame = CreateCompositorFrame(root_rect, &root_pass); @@ -260,7 +261,7 @@ // Verify that point (100, 100) no longer falls on the child surface. // Verify that the transform to the child surface's space has also shifted. { - SurfaceHittest hittest(nullptr, &manager); + SurfaceHittest hittest(nullptr, manager.surface_manager()); gfx::Point point(100, 100); gfx::Transform transform; @@ -286,7 +287,7 @@ // This test verifies that hit testing will progress to the next quad if it // encounters an invalid RenderPassDrawQuad for whatever reason. TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) { - SurfaceManager manager; + FrameSinkManager manager; // Set up root FrameSink. FrameSinkId root_frame_sink_id(1, 1); @@ -390,14 +391,14 @@ } }; - RunTests(nullptr, &manager, tests, arraysize(tests)); + RunTests(nullptr, manager.surface_manager(), tests, arraysize(tests)); root_support->EvictCurrentSurface(); child_support->EvictCurrentSurface(); } TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) { - SurfaceManager manager; + FrameSinkManager manager; FrameSinkId root_frame_sink_id(kArbitraryFrameSinkId); std::unique_ptr<CompositorFrameSinkSupport> support = CompositorFrameSinkSupport::Create( @@ -494,13 +495,13 @@ } }; - RunTests(nullptr, &manager, tests, arraysize(tests)); + RunTests(nullptr, manager.surface_manager(), tests, arraysize(tests)); support->EvictCurrentSurface(); } TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { - SurfaceManager manager; + FrameSinkManager manager; // Set up root FrameSink. FrameSinkId root_frame_sink_id(1, 1); @@ -572,7 +573,8 @@ }; TestSurfaceHittestDelegate empty_delegate; - RunTests(&empty_delegate, &manager, test_expectations_without_insets, + RunTests(&empty_delegate, manager.surface_manager(), + test_expectations_without_insets, arraysize(test_expectations_without_insets)); // Verify that insets have NOT affected hit targeting. @@ -603,7 +605,8 @@ TestSurfaceHittestDelegate reject_delegate; reject_delegate.AddInsetsForRejectSurface(child_surface_id, gfx::Insets(10, 10, 10, 10)); - RunTests(&reject_delegate, &manager, test_expectations_with_reject_insets, + RunTests(&reject_delegate, manager.surface_manager(), + test_expectations_with_reject_insets, arraysize(test_expectations_with_reject_insets)); // Verify that insets have affected hit targeting. @@ -627,7 +630,8 @@ TestSurfaceHittestDelegate accept_delegate; accept_delegate.AddInsetsForAcceptSurface(child_surface_id, gfx::Insets(5, 5, 5, 5)); - RunTests(&accept_delegate, &manager, test_expectations_with_accept_insets, + RunTests(&accept_delegate, manager.surface_manager(), + test_expectations_with_accept_insets, arraysize(test_expectations_with_accept_insets)); // Verify that insets have affected hit targeting.
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index 3e6815e..341fccd 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc
@@ -25,9 +25,9 @@ namespace cc { -SurfaceManager::SurfaceReferenceInfo::SurfaceReferenceInfo() {} +SurfaceManager::SurfaceReferenceInfo::SurfaceReferenceInfo() = default; -SurfaceManager::SurfaceReferenceInfo::~SurfaceReferenceInfo() {} +SurfaceManager::SurfaceReferenceInfo::~SurfaceReferenceInfo() = default; SurfaceManager::SurfaceManager(LifetimeType lifetime_type) : lifetime_type_(lifetime_type), @@ -129,11 +129,12 @@ } void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { - framesink_manager_.RegisterFrameSinkId(frame_sink_id); + bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; + DCHECK(inserted); } void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { - framesink_manager_.InvalidateFrameSinkId(frame_sink_id); + valid_frame_sink_ids_.erase(frame_sink_id); // Remove any temporary references owned by |frame_sink_id|. std::vector<SurfaceId> temp_refs_to_clear; @@ -277,7 +278,7 @@ const SurfaceId& surface_id = map_entry.first; Surface* surface = map_entry.second.get(); surface->SatisfyDestructionDependencies(&satisfied_sequences_, - framesink_manager_.GetValidFrameSinkIds()); + &valid_frame_sink_ids_); if (!IsMarkedForDestruction(surface_id) || surface->GetDestructionDependencyCount() > 0) { @@ -402,45 +403,6 @@ temporary_reference_ranges_.erase(frame_sink_id); } -void SurfaceManager::RegisterFrameSinkManagerClient( - const FrameSinkId& frame_sink_id, - FrameSinkManagerClient* client) { - framesink_manager_.RegisterFrameSinkManagerClient(frame_sink_id, client); -} - -void SurfaceManager::UnregisterFrameSinkManagerClient( - const FrameSinkId& frame_sink_id) { - framesink_manager_.UnregisterFrameSinkManagerClient(frame_sink_id); -} - -void SurfaceManager::RegisterBeginFrameSource( - BeginFrameSource* source, - const FrameSinkId& frame_sink_id) { - framesink_manager_.RegisterBeginFrameSource(source, frame_sink_id); -} - -void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { - framesink_manager_.UnregisterBeginFrameSource(source); -} - -BeginFrameSource* SurfaceManager::GetPrimaryBeginFrameSource() { - return framesink_manager_.GetPrimaryBeginFrameSource(); -} - -void SurfaceManager::RegisterFrameSinkHierarchy( - const FrameSinkId& parent_frame_sink_id, - const FrameSinkId& child_frame_sink_id) { - framesink_manager_.RegisterFrameSinkHierarchy(parent_frame_sink_id, - child_frame_sink_id); -} - -void SurfaceManager::UnregisterFrameSinkHierarchy( - const FrameSinkId& parent_frame_sink_id, - const FrameSinkId& child_frame_sink_id) { - framesink_manager_.UnregisterFrameSinkHierarchy(parent_frame_sink_id, - child_frame_sink_id); -} - Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { DCHECK(thread_checker_.CalledOnValidThread()); auto it = surface_map_.find(surface_id);
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h index a3257e2b..b194c0e5 100644 --- a/cc/surfaces/surface_manager.h +++ b/cc/surfaces/surface_manager.h
@@ -20,7 +20,6 @@ #include "base/observer_list.h" #include "base/threading/thread_checker.h" #include "cc/surfaces/frame_sink_id.h" -#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface_dependency_tracker.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_observer.h" @@ -38,9 +37,7 @@ struct BeginFrameAck; struct BeginFrameArgs; -class BeginFrameSource; class CompositorFrame; -class FrameSinkManagerClient; class Surface; namespace test { @@ -132,35 +129,6 @@ // possibly because a renderer process has crashed. void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id); - // SurfaceClient, hierarchy, and BeginFrameSource can be registered and - // unregistered in any order with respect to each other. - // - // This happens in practice, e.g. the relationship to between ui::Compositor / - // DelegatedFrameHost is known before ui::Compositor has a surface/client). - // However, DelegatedFrameHost can register itself as a client before its - // relationship with the ui::Compositor is known. - - // Associates a FrameSinkManagerClient with the surface id frame_sink_id it - // uses. - // FrameSinkManagerClient and surface namespaces/allocators have a 1:1 - // mapping. Caller guarantees the client is alive between register/unregister. - // Reregistering the same namespace when a previous client is active is not - // valid. - void RegisterFrameSinkManagerClient(const FrameSinkId& frame_sink_id, - FrameSinkManagerClient* client); - void UnregisterFrameSinkManagerClient(const FrameSinkId& frame_sink_id); - - // Associates a |source| with a particular namespace. That namespace and - // any children of that namespace with valid clients can potentially use - // that |source|. - void RegisterBeginFrameSource(BeginFrameSource* source, - const FrameSinkId& frame_sink_id); - void UnregisterBeginFrameSource(BeginFrameSource* source); - - // Returns a stable BeginFrameSource that forwards BeginFrames from the first - // available BeginFrameSource. - BeginFrameSource* GetPrimaryBeginFrameSource(); - // Register a relationship between two namespaces. This relationship means // that surfaces from the child namespace will be displayed in the parent. // Children are allowed to use any begin frame source that their parent can @@ -183,8 +151,8 @@ // collection to delete unreachable surfaces. void RemoveSurfaceReferences(const std::vector<SurfaceReference>& references); - // Assigns |frame_sink_id| as the owner of the temporary reference to - // |surface_id|. If |frame_sink_id| is invalidated the temporary reference + // Assigns |owner| as the owner of the temporary reference to + // |surface_id|. If |owner| is invalidated the temporary reference // will be removed. If a surface reference has already been added from the // parent to |surface_id| then this will do nothing. void AssignTemporaryReference(const SurfaceId& surface_id, @@ -205,7 +173,7 @@ const base::flat_set<SurfaceId>& GetSurfacesThatReferenceChild( const SurfaceId& surface_id) const; - scoped_refptr<SurfaceReferenceFactory> reference_factory() { + const scoped_refptr<SurfaceReferenceFactory>& reference_factory() { return reference_factory_; } @@ -213,6 +181,10 @@ return lifetime_type_ == LifetimeType::REFERENCES; } + const base::flat_set<FrameSinkId>& GetValidFrameSinkIds() { + return valid_frame_sink_ids_; + } + private: friend class test::SurfaceSynchronizationTest; friend class SurfaceManagerRefTest; @@ -279,8 +251,6 @@ // Use reference or sequence based lifetime management. LifetimeType lifetime_type_; - FrameSinkManager framesink_manager_; - // SurfaceDependencyTracker needs to be destroyed after Surfaces are destroyed // because they will call back into the dependency tracker. SurfaceDependencyTracker dependency_tracker_; @@ -293,7 +263,12 @@ // Set of SurfaceSequences that have been satisfied by a frame but not yet // waited on. - std::unordered_set<SurfaceSequence, SurfaceSequenceHash> satisfied_sequences_; + base::flat_set<SurfaceSequence> satisfied_sequences_; + + // Set of valid FrameSinkIds. When a FrameSinkId is removed from + // this set, any remaining (surface) sequences with that FrameSinkId are + // considered satisfied. + base::flat_set<FrameSinkId> valid_frame_sink_ids_; // Root SurfaceId that references display root surfaces. There is no Surface // with this id, it's for bookkeeping purposes only.
diff --git a/cc/surfaces/surface_manager_ref_unittest.cc b/cc/surfaces/surface_manager_ref_unittest.cc index c3518e7..9385a95 100644 --- a/cc/surfaces/surface_manager_ref_unittest.cc +++ b/cc/surfaces/surface_manager_ref_unittest.cc
@@ -10,6 +10,7 @@ #include "base/containers/flat_set.h" #include "base/memory/ptr_util.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_manager.h" @@ -34,7 +35,7 @@ // Tests for reference tracking in SurfaceManager. class SurfaceManagerRefTest : public testing::Test { public: - SurfaceManager& manager() { return *manager_; } + SurfaceManager& GetSurfaceManager() { return *manager_->surface_manager(); } // Creates a new Surface with the provided |frame_sink_id| and |local_id|. // Will first create a Surfacesupport for |frame_sink_id| if necessary. @@ -74,31 +75,33 @@ void RemoveSurfaceReference(const SurfaceId& parent_id, const SurfaceId& child_id) { - manager_->RemoveSurfaceReferences({SurfaceReference(parent_id, child_id)}); + manager_->surface_manager()->RemoveSurfaceReferences( + {SurfaceReference(parent_id, child_id)}); } void AddSurfaceReference(const SurfaceId& parent_id, const SurfaceId& child_id) { - manager_->AddSurfaceReferences({SurfaceReference(parent_id, child_id)}); + manager_->surface_manager()->AddSurfaceReferences( + {SurfaceReference(parent_id, child_id)}); } // Returns all the references where |surface_id| is the parent. const base::flat_set<SurfaceId>& GetReferencesFrom( const SurfaceId& surface_id) { - return manager().GetSurfacesReferencedByParent(surface_id); + return GetSurfaceManager().GetSurfacesReferencedByParent(surface_id); } // Returns all the references where |surface_id| is the child. const base::flat_set<SurfaceId>& GetReferencesFor( const SurfaceId& surface_id) { - return manager().GetSurfacesThatReferenceChild(surface_id); + return GetSurfaceManager().GetSurfacesThatReferenceChild(surface_id); } // Temporary references are stored as a map in SurfaceManager. This method // converts the map to a vector. std::vector<SurfaceId> GetAllTempReferences() { std::vector<SurfaceId> temp_references; - for (auto& map_entry : manager().temporary_references_) + for (auto& map_entry : GetSurfaceManager().temporary_references_) temp_references.push_back(map_entry.first); return temp_references; } @@ -107,7 +110,7 @@ // testing::Test: void SetUp() override { // Start each test with a fresh SurfaceManager instance. - manager_ = base::MakeUnique<SurfaceManager>( + manager_ = base::MakeUnique<FrameSinkManager>( SurfaceManager::LifetimeType::REFERENCES); } void TearDown() override { @@ -121,26 +124,26 @@ std::unique_ptr<CompositorFrameSinkSupport>, FrameSinkIdHash> supports_; - std::unique_ptr<SurfaceManager> manager_; + std::unique_ptr<FrameSinkManager> manager_; }; TEST_F(SurfaceManagerRefTest, AddReference) { SurfaceId id1 = CreateSurface(kFrameSink1, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); EXPECT_THAT(GetReferencesFor(id1), - UnorderedElementsAre(manager().GetRootSurfaceId())); + UnorderedElementsAre(GetSurfaceManager().GetRootSurfaceId())); EXPECT_THAT(GetReferencesFrom(id1), IsEmpty()); } TEST_F(SurfaceManagerRefTest, AddRemoveReference) { SurfaceId id1 = CreateSurface(kFrameSink1, 1); SurfaceId id2 = CreateSurface(kFrameSink2, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); AddSurfaceReference(id1, id2); EXPECT_THAT(GetReferencesFor(id1), - UnorderedElementsAre(manager().GetRootSurfaceId())); + UnorderedElementsAre(GetSurfaceManager().GetRootSurfaceId())); EXPECT_THAT(GetReferencesFor(id2), UnorderedElementsAre(id1)); EXPECT_THAT(GetReferencesFrom(id1), UnorderedElementsAre(id2)); EXPECT_THAT(GetReferencesFrom(id2), IsEmpty()); @@ -157,15 +160,15 @@ SurfaceId id2 = CreateSurface(kFrameSink2, 1); SurfaceId id3 = CreateSurface(kFrameSink3, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); AddSurfaceReference(id1, id2); AddSurfaceReference(id2, id3); // |kFramesink2| received a CompositorFrame with a new size, so it destroys // |id2| and creates |id2_next|. No reference have been removed yet. SurfaceId id2_next = CreateSurface(kFrameSink2, 2); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2_next)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2_next)); // Add references to and from |id2_next|. AddSurfaceReference(id1, id2_next); @@ -180,9 +183,9 @@ EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2_next)); // |id2| should be deleted during GC but other surfaces shouldn't. - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2_next)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id3)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2_next)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); } TEST_F(SurfaceManagerRefTest, ReferenceCycleGetsDeleted) { @@ -190,7 +193,7 @@ SurfaceId id2 = CreateSurface(kFrameSink2, 1); SurfaceId id3 = CreateSurface(kFrameSink3, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); AddSurfaceReference(id1, id2); AddSurfaceReference(id2, id3); @@ -201,39 +204,39 @@ DestroySurface(id2); DestroySurface(id1); - RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); + RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); // Removing the reference from the root to id1 should allow all three surfaces // to be deleted during GC even with a cycle between 2 and 3. - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id3)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); } TEST_F(SurfaceManagerRefTest, SurfacesAreDeletedDuringGarbageCollection) { SurfaceId id1 = CreateSurface(kFrameSink1, 1); SurfaceId id2 = CreateSurface(kFrameSink2, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); AddSurfaceReference(id1, id2); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id1)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // Destroying the surfaces shouldn't delete them yet, since there is still an // active reference on all surfaces. DestroySurface(id1); DestroySurface(id2); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id1)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // Should delete |id2| when the only reference to it is removed. RemoveSurfaceReference(id1, id2); - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // Should delete |id1| when the only reference to it is removed. - RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); + RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); } TEST_F(SurfaceManagerRefTest, GarbageCollectionWorksRecusively) { @@ -241,7 +244,7 @@ SurfaceId id2 = CreateSurface(kFrameSink2, 1); SurfaceId id3 = CreateSurface(kFrameSink3, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); AddSurfaceReference(id1, id2); AddSurfaceReference(id2, id3); @@ -251,24 +254,24 @@ // Destroying the surfaces shouldn't delete them yet, since there is still an // active reference on all surfaces. - EXPECT_NE(nullptr, manager().GetSurfaceForId(id3)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id1)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); - RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); + RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); // Removing the reference from the root to id1 should allow all three surfaces // to be deleted during GC. - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id3)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id3)); } TEST_F(SurfaceManagerRefTest, TryAddReferenceSameReferenceTwice) { SurfaceId id1 = CreateSurface(kFrameSink1, 1); SurfaceId id2 = CreateSurface(kFrameSink2, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); AddSurfaceReference(id1, id2); EXPECT_THAT(GetReferencesFor(id2), SizeIs(1)); EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1)); @@ -334,12 +337,12 @@ EXPECT_THAT(GetAllTempReferences(), ElementsAre(surface_id)); // Add a real reference from root to |surface_id|. - AddSurfaceReference(manager().GetRootSurfaceId(), surface_id); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), surface_id); // The temporary reference should be gone and there should now be a surface // reference from root to |surface_id|. EXPECT_TRUE(GetAllTempReferences().empty()); - EXPECT_THAT(GetReferencesFrom(manager().GetRootSurfaceId()), + EXPECT_THAT(GetReferencesFrom(GetSurfaceManager().GetRootSurfaceId()), ElementsAre(surface_id)); } @@ -415,25 +418,25 @@ TEST_F(SurfaceManagerRefTest, SurfaceWithTemporaryReferenceIsNotDeleted) { const SurfaceId id1 = CreateSurface(kFrameSink1, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), id1); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); // We create |id2| and never add a real reference to it. This leaves the // temporary reference. const SurfaceId id2 = CreateSurface(kFrameSink2, 1); ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id2)); - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); // Destroy both surfaces so they can be garbage collected. We remove the // surface reference to |id1| which will run GarbageCollectSurfaces(). DestroySurface(id1); DestroySurface(id2); - RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); + RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1); // |id1| is destroyed and has no references, so it's deleted. - EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); + EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1)); // |id2| is destroyed but has a temporary reference, it's not deleted. - EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2)); } // Checks that when a temporary reference is assigned an owner, if the owner is @@ -444,11 +447,11 @@ ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id1)); // |id1| should have a temporary reference after an owner is assigned. - manager().AssignTemporaryReference(id1, kFrameSink1); + GetSurfaceManager().AssignTemporaryReference(id1, kFrameSink1); ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id1)); // When |kFrameSink1| is invalidated the temporary reference will be removed. - manager().InvalidateFrameSinkId(kFrameSink1); + GetSurfaceManager().InvalidateFrameSinkId(kFrameSink1); ASSERT_THAT(GetAllTempReferences(), IsEmpty()); } @@ -456,10 +459,10 @@ // ownership. Invalidating the old owner shouldn't do anything. TEST_F(SurfaceManagerRefTest, InvalidateHasNoEffectOnSurfaceReferences) { const SurfaceId parent_id = CreateSurface(kFrameSink1, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), parent_id); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), parent_id); const SurfaceId id1 = CreateSurface(kFrameSink2, 1); - manager().AssignTemporaryReference(id1, kFrameSink1); + GetSurfaceManager().AssignTemporaryReference(id1, kFrameSink1); ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id1)); // Adding a real surface reference will remove the temporary reference. @@ -480,7 +483,7 @@ // An example of why this could happen is the window server doesn't know the // owner, maybe it has crashed and been cleanup already, and asks to drop the // temporary reference. - manager().DropTemporaryReference(id1); + GetSurfaceManager().DropTemporaryReference(id1); ASSERT_THAT(GetAllTempReferences(), IsEmpty()); } @@ -489,7 +492,7 @@ // client crashing, so it's TEST_F(SurfaceManagerRefTest, TempReferencesWithClientCrash) { const SurfaceId parent_id = CreateSurface(kFrameSink1, 1); - AddSurfaceReference(manager().GetRootSurfaceId(), parent_id); + AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), parent_id); const SurfaceId id1a = CreateSurface(kFrameSink2, 1); const SurfaceId id1b = CreateSurface(kFrameSink2, 2); @@ -498,7 +501,7 @@ // Assign |id1a| to |kFrameSink1|. This doesn't change the temporary // reference, it just assigns as owner to it. - manager().AssignTemporaryReference(id1a, kFrameSink1); + GetSurfaceManager().AssignTemporaryReference(id1a, kFrameSink1); ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id1a, id1b)); // If the parent client crashes then the FrameSink connection will be closed @@ -510,7 +513,7 @@ // If the parent has crashed then the window server will have already removed // it from the ServerWindow hierarchy and won't have an owner for |id2b|. The // window server will ask to drop the reference instead. - manager().DropTemporaryReference(id1b); + GetSurfaceManager().DropTemporaryReference(id1b); ASSERT_THAT(GetAllTempReferences(), IsEmpty()); }
diff --git a/cc/surfaces/surface_synchronization_unittest.cc b/cc/surfaces/surface_synchronization_unittest.cc index 02c35f3..dd7ee7d 100644 --- a/cc/surfaces/surface_synchronization_unittest.cc +++ b/cc/surfaces/surface_synchronization_unittest.cc
@@ -4,8 +4,8 @@ #include "base/containers/flat_set.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface_id.h" -#include "cc/surfaces/surface_manager.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/compositor_frame_helpers.h" #include "cc/test/fake_external_begin_frame_source.h" @@ -70,7 +70,7 @@ class SurfaceSynchronizationTest : public testing::Test { public: SurfaceSynchronizationTest() - : surface_manager_(SurfaceManager::LifetimeType::REFERENCES), + : frame_sink_manager_(SurfaceManager::LifetimeType::REFERENCES), surface_observer_(false) {} ~SurfaceSynchronizationTest() override {} @@ -99,17 +99,20 @@ return support(index).GetCurrentSurfaceForTesting(); } - SurfaceManager& surface_manager() { return surface_manager_; } + FrameSinkManager& frame_sink_manager() { return frame_sink_manager_; } // Returns all the references where |surface_id| is the parent. const base::flat_set<SurfaceId>& GetChildReferences( const SurfaceId& surface_id) { - return surface_manager().GetSurfacesReferencedByParent(surface_id); + return frame_sink_manager() + .surface_manager() + ->GetSurfacesReferencedByParent(surface_id); } // Returns true if there is a temporary reference for |surface_id|. bool HasTemporaryReference(const SurfaceId& surface_id) { - return surface_manager().HasTemporaryReference(surface_id); + return frame_sink_manager().surface_manager()->HasTemporaryReference( + surface_id); } FakeExternalBeginFrameSource* begin_frame_source() { @@ -135,31 +138,31 @@ base::MakeUnique<FakeExternalBeginFrameSource>(0.f, false); begin_frame_source_->SetClient(&begin_frame_source_client_); now_src_ = base::MakeUnique<base::SimpleTestTickClock>(); - surface_manager_.AddObserver(&surface_observer_); + frame_sink_manager_.surface_manager()->AddObserver(&surface_observer_); supports_.push_back(CompositorFrameSinkSupport::Create( - &support_client_, &surface_manager_, kDisplayFrameSink, kIsRoot, + &support_client_, &frame_sink_manager_, kDisplayFrameSink, kIsRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)); supports_.push_back(CompositorFrameSinkSupport::Create( - &support_client_, &surface_manager_, kParentFrameSink, kIsChildRoot, + &support_client_, &frame_sink_manager_, kParentFrameSink, kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)); supports_.push_back(CompositorFrameSinkSupport::Create( - &support_client_, &surface_manager_, kChildFrameSink1, kIsChildRoot, + &support_client_, &frame_sink_manager_, kChildFrameSink1, kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)); supports_.push_back(CompositorFrameSinkSupport::Create( - &support_client_, &surface_manager_, kChildFrameSink2, kIsChildRoot, + &support_client_, &frame_sink_manager_, kChildFrameSink2, kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints)); // Normally, the BeginFrameSource would be registered by the Display. We // register it here so that BeginFrames are received by the display support, // for use in the PassesOnBeginFrameAcks test. Other supports do not receive // BeginFrames, since the frame sink hierarchy is not set up in this test. - surface_manager_.RegisterBeginFrameSource(begin_frame_source_.get(), - kDisplayFrameSink); + frame_sink_manager_.RegisterBeginFrameSource(begin_frame_source_.get(), + kDisplayFrameSink); } void TearDown() override { - surface_manager_.RemoveObserver(&surface_observer_); - surface_manager_.UnregisterBeginFrameSource(begin_frame_source_.get()); + frame_sink_manager_.surface_manager()->RemoveObserver(&surface_observer_); + frame_sink_manager_.UnregisterBeginFrameSource(begin_frame_source_.get()); begin_frame_source_->SetClient(nullptr); begin_frame_source_.reset(); @@ -170,14 +173,19 @@ } bool IsMarkedForDestruction(const SurfaceId& surface_id) { - return surface_manager_.IsMarkedForDestruction(surface_id); + return frame_sink_manager_.surface_manager()->IsMarkedForDestruction( + surface_id); + } + + Surface* GetSurfaceForId(const SurfaceId& surface_id) { + return frame_sink_manager_.surface_manager()->GetSurfaceForId(surface_id); } protected: testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_; private: - SurfaceManager surface_manager_; + FrameSinkManager frame_sink_manager_; FakeSurfaceObserver surface_observer_; FakeExternalBeginFrameSourceClient begin_frame_source_client_; std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_; @@ -200,7 +208,8 @@ // A surface reference from the top-level root is added and there shouldn't be // a temporary reference. EXPECT_FALSE(HasTemporaryReference(display_id_first)); - EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()), + EXPECT_THAT(GetChildReferences( + frame_sink_manager().surface_manager()->GetRootSurfaceId()), UnorderedElementsAre(display_id_first)); // Submit a CompositorFrame for the second display root surface. @@ -210,11 +219,12 @@ // A surface reference from the top-level root to |display_id_second| should // be added and the reference to |display_root_first| removed. EXPECT_FALSE(HasTemporaryReference(display_id_second)); - EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()), + EXPECT_THAT(GetChildReferences( + frame_sink_manager().surface_manager()->GetRootSurfaceId()), UnorderedElementsAre(display_id_second)); // Surface |display_id_first| is unreachable and should get deleted. - EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(display_id_first)); + EXPECT_EQ(nullptr, GetSurfaceForId(display_id_first)); } // The parent Surface is blocked on |child_id1| and |child_id2|. @@ -756,7 +766,7 @@ std::move(frame)); // Verify that the old surface has an active frame and no pending frame. - Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1); + Surface* old_surface = GetSurfaceForId(parent_id1); ASSERT_NE(nullptr, old_surface); EXPECT_TRUE(old_surface->HasActiveFrame()); EXPECT_FALSE(old_surface->HasPendingFrame()); @@ -773,7 +783,7 @@ std::move(frame2)); // Verify that the new surface has an active frame and no pending frames. - Surface* surface = surface_manager().GetSurfaceForId(parent_id2); + Surface* surface = GetSurfaceForId(parent_id2); ASSERT_NE(nullptr, surface); EXPECT_TRUE(surface->HasActiveFrame()); EXPECT_FALSE(surface->HasPendingFrame()); @@ -839,7 +849,7 @@ std::move(frame2)); // Verify that the old surface has both an active and a pending frame. - Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1); + Surface* old_surface = GetSurfaceForId(parent_id1); ASSERT_NE(nullptr, old_surface); EXPECT_TRUE(old_surface->HasActiveFrame()); EXPECT_TRUE(old_surface->HasPendingFrame()); @@ -849,7 +859,7 @@ MakeCompositorFrame()); // Verify that the new surface has an active frame only. - Surface* surface = surface_manager().GetSurfaceForId(parent_id2); + Surface* surface = GetSurfaceForId(parent_id2); ASSERT_NE(nullptr, surface); EXPECT_TRUE(surface->HasActiveFrame()); EXPECT_FALSE(surface->HasPendingFrame()); @@ -905,7 +915,7 @@ std::move(frame)); // Verify that the old surface has an active frame only. - Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1); + Surface* old_surface = GetSurfaceForId(parent_id1); ASSERT_NE(nullptr, old_surface); EXPECT_TRUE(old_surface->HasActiveFrame()); EXPECT_FALSE(old_surface->HasPendingFrame()); @@ -923,7 +933,7 @@ std::move(frame2)); // Verify that the new surface has a pending frame and no active frame. - Surface* surface = surface_manager().GetSurfaceForId(parent_id2); + Surface* surface = GetSurfaceForId(parent_id2); ASSERT_NE(nullptr, surface); EXPECT_TRUE(surface->HasPendingFrame()); EXPECT_FALSE(surface->HasActiveFrame()); @@ -983,12 +993,12 @@ const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3); // Create the child surface by submitting a frame to it. - EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id)); + EXPECT_EQ(nullptr, GetSurfaceForId(child_id)); child_support1().SubmitCompositorFrame(child_id.local_surface_id(), MakeCompositorFrame()); // Verify that the child surface is created. - Surface* surface = surface_manager().GetSurfaceForId(child_id); + Surface* surface = GetSurfaceForId(child_id); EXPECT_NE(nullptr, surface); // Add a reference from the parent to the child. @@ -1000,7 +1010,7 @@ // Attempt to destroy the child surface. The surface must still exist since // the parent needs it but it will be marked as destroyed. child_support1().EvictCurrentSurface(); - surface = surface_manager().GetSurfaceForId(child_id); + surface = GetSurfaceForId(child_id); EXPECT_NE(nullptr, surface); EXPECT_TRUE(IsMarkedForDestruction(child_id)); @@ -1011,7 +1021,7 @@ // Verify that the surface that was marked destroyed is recovered and is being // used again. - Surface* surface2 = surface_manager().GetSurfaceForId(child_id); + Surface* surface2 = GetSurfaceForId(child_id); EXPECT_EQ(surface, surface2); EXPECT_FALSE(IsMarkedForDestruction(child_id)); } @@ -1025,7 +1035,7 @@ // Submit the first frame. Creates the surface. child_support1().SubmitCompositorFrame(child_id.local_surface_id(), MakeCompositorFrame()); - EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id)); + EXPECT_NE(nullptr, GetSurfaceForId(child_id)); // Add a reference from parent. parent_support().SubmitCompositorFrame( @@ -1039,13 +1049,13 @@ // Destroy the surface. child_support1().EvictCurrentSurface(); - EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id)); + EXPECT_EQ(nullptr, GetSurfaceForId(child_id)); // Submit another frame with the same local surface id. This should work fine // and a new surface must be created. child_support1().SubmitCompositorFrame(child_id.local_surface_id(), MakeCompositorFrame()); - EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id)); + EXPECT_NE(nullptr, GetSurfaceForId(child_id)); } // This test verifies that a crash does not occur if garbage collection is
diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc index 297a1670..ff6316595 100644 --- a/cc/surfaces/surface_unittest.cc +++ b/cc/surfaces/surface_unittest.cc
@@ -6,8 +6,9 @@ #include "base/memory/ptr_util.h" #include "cc/output/copy_output_result.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" +#include "cc/surfaces/surface_dependency_tracker.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/compositor_frame_helpers.h" #include "cc/test/fake_external_begin_frame_source.h" @@ -24,19 +25,20 @@ constexpr bool kNeedsSyncPoints = true; TEST(SurfaceTest, SurfaceLifetime) { - SurfaceManager manager; + FrameSinkManager frame_sink_manager; + SurfaceManager* surface_manager = frame_sink_manager.surface_manager(); std::unique_ptr<CompositorFrameSinkSupport> support = CompositorFrameSinkSupport::Create( - nullptr, &manager, kArbitraryFrameSinkId, kIsRoot, + nullptr, &frame_sink_manager, kArbitraryFrameSinkId, kIsRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); support->SubmitCompositorFrame(local_surface_id, test::MakeCompositorFrame()); - EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); + EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id)); support->EvictCurrentSurface(); - EXPECT_EQ(NULL, manager.GetSurfaceForId(surface_id)); + EXPECT_EQ(NULL, surface_manager->GetSurfaceForId(surface_id)); } TEST(SurfaceTest, SurfaceIds) { @@ -56,23 +58,24 @@ // Test that CopyOutputRequests can outlive the current frame and be // aggregated on the next frame. TEST(SurfaceTest, CopyRequestLifetime) { - SurfaceManager manager; + FrameSinkManager frame_sink_manager; + SurfaceManager* surface_manager = frame_sink_manager.surface_manager(); std::unique_ptr<CompositorFrameSinkSupport> support = CompositorFrameSinkSupport::Create( - nullptr, &manager, kArbitraryFrameSinkId, kIsRoot, + nullptr, &frame_sink_manager, kArbitraryFrameSinkId, kIsRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints); LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); CompositorFrame frame = test::MakeCompositorFrame(); support->SubmitCompositorFrame(local_surface_id, std::move(frame)); - Surface* surface = manager.GetSurfaceForId(surface_id); + Surface* surface = surface_manager->GetSurfaceForId(surface_id); ASSERT_TRUE(!!surface); bool copy_called = false; support->RequestCopyOfSurface(CopyOutputRequest::CreateRequest( base::Bind(&TestCopyResultCallback, ©_called))); - EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); + EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id)); EXPECT_FALSE(copy_called); int max_frame = 3, start_id = 200;
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc index 2917c086..aabb74a 100644 --- a/cc/surfaces/surfaces_pixeltest.cc +++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -7,6 +7,7 @@ #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/surface_draw_quad.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_aggregator.h" @@ -43,7 +44,7 @@ ~SurfacesPixelTest() override { support_->EvictCurrentSurface(); } protected: - SurfaceManager manager_; + FrameSinkManager manager_; LocalSurfaceIdAllocator allocator_; std::unique_ptr<CompositorFrameSinkSupport> support_; }; @@ -90,7 +91,8 @@ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id); support_->SubmitCompositorFrame(root_local_surface_id, std::move(root_frame)); - SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); + SurfaceAggregator aggregator(manager_.surface_manager(), + resource_provider_.get(), true); CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); bool discard_alpha = false; @@ -172,7 +174,8 @@ std::move(child_frame)); } - SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); + SurfaceAggregator aggregator(manager_.surface_manager(), + resource_provider_.get(), true); CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); bool discard_alpha = false; @@ -313,7 +316,8 @@ std::move(child_frame)); } - SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); + SurfaceAggregator aggregator(manager_.surface_manager(), + resource_provider_.get(), true); CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); bool discard_alpha = false;
diff --git a/cc/test/test_layer_tree_frame_sink.cc b/cc/test/test_layer_tree_frame_sink.cc index 0ef669a1..9e93c09 100644 --- a/cc/test/test_layer_tree_frame_sink.cc +++ b/cc/test/test_layer_tree_frame_sink.cc
@@ -41,8 +41,8 @@ refresh_rate_(refresh_rate), task_runner_(std::move(task_runner)), frame_sink_id_(kLayerTreeFrameSinkId), - surface_manager_(new SurfaceManager), - local_surface_id_allocator_(new LocalSurfaceIdAllocator()), + frame_sink_manager_(new FrameSinkManager), + local_surface_id_allocator_(new LocalSurfaceIdAllocator), external_begin_frame_source_(this), weak_ptr_factory_(this) { // Always use sync tokens so that code paths in resource provider that deal @@ -99,14 +99,14 @@ constexpr bool handles_frame_sink_id_invalidation = true; constexpr bool needs_sync_points = true; support_ = CompositorFrameSinkSupport::Create( - this, surface_manager_.get(), frame_sink_id_, is_root, + this, frame_sink_manager_.get(), frame_sink_id_, is_root, handles_frame_sink_id_invalidation, needs_sync_points); client_->SetBeginFrameSource(&external_begin_frame_source_); if (begin_frame_source_) { - surface_manager_->RegisterBeginFrameSource(begin_frame_source_.get(), - frame_sink_id_); + frame_sink_manager_->RegisterBeginFrameSource(begin_frame_source_.get(), + frame_sink_id_); } - display_->Initialize(this, surface_manager_.get()); + display_->Initialize(this, frame_sink_manager_->surface_manager()); display_->renderer_for_testing()->SetEnlargePassTextureAmountForTesting( enlarge_pass_texture_amount_); display_->SetVisible(true); @@ -115,13 +115,13 @@ void TestLayerTreeFrameSink::DetachFromClient() { if (begin_frame_source_) - surface_manager_->UnregisterBeginFrameSource(begin_frame_source_.get()); + frame_sink_manager_->UnregisterBeginFrameSource(begin_frame_source_.get()); client_->SetBeginFrameSource(nullptr); support_ = nullptr; display_ = nullptr; begin_frame_source_ = nullptr; local_surface_id_allocator_ = nullptr; - surface_manager_ = nullptr; + frame_sink_manager_ = nullptr; test_client_ = nullptr; LayerTreeFrameSink::DetachFromClient(); }
diff --git a/cc/test/test_layer_tree_frame_sink.h b/cc/test/test_layer_tree_frame_sink.h index ed72e96..8feb90a8 100644 --- a/cc/test/test_layer_tree_frame_sink.h +++ b/cc/test/test_layer_tree_frame_sink.h
@@ -13,8 +13,8 @@ #include "cc/surfaces/compositor_frame_sink_support_client.h" #include "cc/surfaces/display.h" #include "cc/surfaces/display_client.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" namespace base { class SingleThreadTaskRunner; @@ -113,7 +113,7 @@ FrameSinkId frame_sink_id_; // TODO(danakj): These don't need to be stored in unique_ptrs when // LayerTreeFrameSink is owned/destroyed on the compositor thread. - std::unique_ptr<SurfaceManager> surface_manager_; + std::unique_ptr<FrameSinkManager> frame_sink_manager_; std::unique_ptr<LocalSurfaceIdAllocator> local_surface_id_allocator_; LocalSurfaceId local_surface_id_; gfx::Size display_size_;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 707d7a75..99f22caa 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -4124,7 +4124,6 @@ data.opaque = bitmap.GetOpaque(); ui_resource_map_[uid] = data; - resource_provider_->GenerateSyncTokenForResource(id); MarkUIResourceNotEvicted(uid); }
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 7cd13b9..ccd3744 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1767,6 +1767,7 @@ deps += [ "//device/gamepad", "//device/sensors", + "//ui/events/devices", ] } }
diff --git a/chrome/VERSION b/chrome/VERSION index f73397dc..c1e4964 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=61 MINOR=0 -BUILD=3151 +BUILD=3152 PATCH=0
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index bcec228a..618cb09 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -485,4 +485,8 @@ <!-- Search widget dimensions --> <dimen name="search_activity_location_bar_margin_start">16dp</dimen> <dimen name="search_activity_location_bar_margin_end">8dp</dimen> + + <!-- Reader Mode dimensions --> + <!-- Padding surrounding the message. --> + <dimen name="reader_mode_infobar_text_padding">8dp</dimen> </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index df794bf..c8238aea 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1732,14 +1732,7 @@ if (!mUIInitialized) return false; final Tab currentTab = getActivityTab(); - // Close the bottom sheet before trying to navigate back. - if (getBottomSheet() != null - && getBottomSheet().getSheetState() != BottomSheet.SHEET_STATE_PEEK) { - getBottomSheet().getBottomSheetMetrics().setSheetCloseReason( - BottomSheetMetrics.CLOSED_BY_BACK_PRESS); - getBottomSheet().setSheetState(BottomSheet.SHEET_STATE_PEEK, true); - return true; - } + if (getBottomSheet() != null && getBottomSheet().handleBackPress()) return true; if (currentTab == null) { recordBackPressedUma("currentTab is null", BACK_PRESSED_TAB_IS_NULL);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java index 939a3d62..cc6da7b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser; +import android.app.Activity; import android.app.KeyguardManager; import android.app.PendingIntent; import android.app.SearchManager; @@ -183,7 +184,8 @@ private static final String PACKAGE_MESSENGER = "com.google.android.apps.messaging"; private static final String PACKAGE_LINE = "jp.naver.line.android"; private static final String PACKAGE_WHATSAPP = "com.whatsapp"; - private static final String FACEBOOK_LINK_PREFIX = "http://m.facebook.com/l.php?"; + private static final String FACEBOOK_REFERRER_URL = "android-app://m.facebook.com"; + private static final String FACEBOOK_INTERNAL_BROWSER_REFERRER = "http://m.facebook.com"; private static final String TWITTER_LINK_PREFIX = "http://t.co/"; private static final String NEWS_LINK_PREFIX = "http://news.google.com/news/url?"; @@ -292,12 +294,22 @@ ExternalAppId externalId = ExternalAppId.OTHER; if (appId == null) { String url = getUrlFromIntent(intent); + String referrer = getReferrerUrl(intent); if (url != null && url.startsWith(TWITTER_LINK_PREFIX)) { externalId = ExternalAppId.TWITTER; - } else if (url != null && url.startsWith(FACEBOOK_LINK_PREFIX)) { + } else if (FACEBOOK_REFERRER_URL.equals(referrer)) { + // This happens when "Links Open Externally" is checked in the Facebook app. externalId = ExternalAppId.FACEBOOK; } else if (url != null && url.startsWith(NEWS_LINK_PREFIX)) { externalId = ExternalAppId.NEWS; + } else { + Bundle headers = IntentUtils.safeGetBundleExtra(intent, Browser.EXTRA_HEADERS); + if (headers != null + && FACEBOOK_INTERNAL_BROWSER_REFERRER.equals(headers.get("Referer"))) { + // This happens when "Links Open Externally" is unchecked in the Facebook app, + // and we use "Open With..." from the internal browser. + externalId = ExternalAppId.FACEBOOK; + } } } else { if (appId.equals(PACKAGE_PLUS)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java index b8adf07..0212c7d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java
@@ -200,6 +200,7 @@ .setNegativeButton(R.string.cancel, null) .setPositiveButton(confirmButtonLabel, null) .create(); + mDialog.setCanceledOnTouchOutside(false); mDialog.setOnDismissListener(this); mShouldRequestExpirationDate = shouldRequestExpirationDate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index bddb157a..66032ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -505,7 +505,7 @@ if (baseWebContents == null) return null; try { - return new URL(baseWebContents.getUrl()); + return new URL(baseWebContents.getLastCommittedUrl()); } catch (MalformedURLException e) { return null; } @@ -1163,7 +1163,7 @@ } /** - * Gets the current loaded URL in a ContentViewCore. + * Gets the currently loading or loaded URL in a ContentViewCore. * * @param searchContentViewCore The given ContentViewCore. * @return The current loaded URL. @@ -1173,8 +1173,8 @@ // not yet committed being processed. Otherwise, get the URL from the WebContents. NavigationEntry entry = searchContentViewCore.getWebContents().getNavigationController().getPendingEntry(); - String url = - entry != null ? entry.getUrl() : searchContentViewCore.getWebContents().getUrl(); + String url = entry != null ? entry.getUrl() + : searchContentViewCore.getWebContents().getLastCommittedUrl(); return url; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index 4067eb9..8288d30 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -390,7 +390,7 @@ WebContents baseWebContents = getBasePageWebContents(); if (baseWebContents == null || mChromeActivity == null || mTabModelSelector == null) return; - String url = baseWebContents.getUrl(); + String url = baseWebContents.getLastCommittedUrl(); if (url == null) return; ReaderModeTabInfo info = mTabStatusMap.get(mTabModelSelector.getCurrentTabId());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarCompactLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarCompactLayout.java index 285ef4f..a613b69 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarCompactLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarCompactLayout.java
@@ -57,9 +57,9 @@ if (weight <= 0.0f) { params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, mCompactInfoBarSize); } else { - params = new LinearLayout.LayoutParams(0, mCompactInfoBarSize); - params.weight = weight; + params = new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT, weight); } + view.setMinimumHeight(mCompactInfoBarSize); params.gravity = Gravity.BOTTOM; addView(view, indexOfChild(mCloseButton), params); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java index 14948a1..e3a895c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java
@@ -48,7 +48,6 @@ protected void createCompactLayoutContent(InfoBarCompactLayout layout) { TextView prompt = new TextView(getContext()); prompt.setText(R.string.reader_view_text); - prompt.setSingleLine(); prompt.setTextSize(TypedValue.COMPLEX_UNIT_PX, getContext().getResources().getDimension(R.dimen.infobar_text_size)); prompt.setTextColor( @@ -57,6 +56,9 @@ prompt.setOnClickListener(mNavigateListener); layout.findViewById(R.id.infobar_icon).setOnClickListener(mNavigateListener); + final int messagePadding = getContext().getResources().getDimensionPixelOffset( + R.dimen.reader_mode_infobar_text_padding); + prompt.setPadding(0, messagePadding, 0, messagePadding); layout.addContent(prompt, 1f); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java index 712e931..dd851e9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java
@@ -11,8 +11,8 @@ import android.widget.TextView; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate; +import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; @@ -59,7 +59,7 @@ new SpanApplier.SpanInfo("<link>", "</link>", link))); textView.setMovementMethod(LinkMovementMethod.getInstance()); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME)) { + if (FeatureUtilities.isChromeHomeEnabled()) { itemView.setPadding(itemView.getPaddingLeft(), root.getResources().getDimensionPixelSize( R.dimen.chrome_home_suggestions_footer_padding_top),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java index eb5f582..b88f6a93 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java
@@ -27,7 +27,7 @@ public void create( WebContents webContents, Set<String> methods, PaymentAppCreatedCallback callback) { AndroidPaymentAppFinder.find(webContents, methods, new PaymentManifestWebDataService(), - new PaymentManifestDownloader(webContents), new PaymentManifestParser(), + new PaymentManifestDownloader(), new PaymentManifestParser(), new PackageManagerDelegate(), callback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java index 9aaa820..8675b11 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java
@@ -182,6 +182,10 @@ // manifest file needs to be parsed. The startup can take up to 2 seconds. if (!mParser.isUtilityProcessRunning()) mParser.startUtilityProcess(); + // Initialize the native side of the downloader, once we know that a manifest file needs + // to be downloaded. + if (!mDownloader.isInitialized()) mDownloader.initialize(mWebContents); + mManifestVerifiers.add( new PaymentManifestVerifier(uriMethodName, supportedApps, mWebDataService, mDownloader, mParser, mPackageManagerDelegate, this /* callback */)); @@ -306,6 +310,7 @@ assert mPendingApps.isEmpty(); mWebDataService.destroy(); + if (mDownloader.isInitialized()) mDownloader.destroy(); if (mParser.isUtilityProcessRunning()) mParser.stopUtilityProcess(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java index 57b0ecc..c865c01 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java
@@ -174,6 +174,13 @@ } } + /** + * Records the fact that the user had an initial form of payment. + */ + public void setUserHadInitialFormOfPayment() { + nativeSetUserHadInitialFormOfPayment(mJourneyLoggerAndroid); + } + private native long nativeInitJourneyLoggerAndroid(boolean isIncognito, String url); private native void nativeDestroy(long nativeJourneyLoggerAndroid); private native void nativeSetNumberOfSuggestionsShown( @@ -194,4 +201,5 @@ private native void nativeSetCompleted(long nativeJourneyLoggerAndroid); private native void nativeSetAborted(long nativeJourneyLoggerAndroid, int reason); private native void nativeSetNotShown(long nativeJourneyLoggerAndroid, int reason); + private native void nativeSetUserHadInitialFormOfPayment(long nativeJourneyLoggerAndroid); } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index 96f253fe..007d652 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -1558,6 +1558,9 @@ mJourneyLogger.setNumberOfSuggestionsShown( Section.CREDIT_CARDS, numberOfAutofillInstruments); + // Record whether the user had a form of payment initially. + if (!mPendingInstruments.isEmpty()) mJourneyLogger.setUserHadInitialFormOfPayment(); + // Possibly pre-select the first instrument on the list. int selection = !mPendingInstruments.isEmpty() && mPendingInstruments.get(0).canPreselect() ? 0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialog.java index db9b9c2..410f8ac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialog.java
@@ -5,10 +5,7 @@ package org.chromium.chrome.browser.photo_picker; import android.content.Context; -import android.os.Bundle; import android.support.v7.app.AlertDialog; -import android.view.ViewGroup.LayoutParams; -import android.view.WindowManager; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; @@ -43,15 +40,6 @@ } @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - @Override public void dismiss() { super.dismiss(); mCategoryView.onDialogDismissed();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java index 97e8b70..100cb87 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java
@@ -7,10 +7,12 @@ import android.support.annotation.Nullable; import org.chromium.base.metrics.RecordUserAction; +import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.NativePageHost; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; +import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.ntp.NewTabPageUma; @@ -31,6 +33,7 @@ import org.chromium.content_public.common.Referrer; import org.chromium.ui.base.PageTransition; import org.chromium.ui.mojom.WindowOpenDisposition; +import org.chromium.ui.widget.Toast; /** * {@link SuggestionsUiDelegate} implementation. @@ -184,8 +187,21 @@ } private Tab openUrlInNewTab(LoadUrlParams loadUrlParams) { - return mTabModelSelector.openNewTab(loadUrlParams, TabLaunchType.FROM_LONGPRESS_BACKGROUND, - mHost.getActiveTab(), /* incognito = */ false); + Tab tab = mTabModelSelector.openNewTab(loadUrlParams, + TabLaunchType.FROM_LONGPRESS_BACKGROUND, mHost.getActiveTab(), + /* incognito = */ false); + + // If the bottom sheet NTP UI is showing, a toast is not necessary because the bottom sheet + // will be closed when the overview is hidden due to the new tab creation above. + // If animations are disabled in the DeviceClassManager, a toast is already displayed for + // all tabs opened in the background. + // TODO(twellington): Replace this with an animation. + if (mActivity.getBottomSheet() != null && !mActivity.getBottomSheet().isShowingNewTab() + && DeviceClassManager.enableAnimations()) { + Toast.makeText(mActivity, R.string.open_in_new_tab_toast, Toast.LENGTH_SHORT).show(); + } + + return tab; } private void saveUrlForOffline(String url) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 05424a1..44be9d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -1312,7 +1312,7 @@ }); if (!creatingWebContents && webContents.isLoadingToDifferentDocument()) { - didStartPageLoad(webContents.getUrl(), false); + didStartPageLoad(webContents.getVisibleUrl(), false); } getAppBannerManager().setIsEnabledForTab(mDelegateFactory.canShowAppBanners(this)); @@ -1890,11 +1890,12 @@ } /** - * @return The URL associated with the tab. + * @return The URL that is currently visible in the location bar. This may not be the same as + * the last committed URL if a new navigation is in progress. */ @CalledByNative public String getUrl() { - String url = getWebContents() != null ? getWebContents().getUrl() : ""; + String url = getWebContents() != null ? getWebContents().getVisibleUrl() : ""; // If we have a ContentView, or a NativePage, or the url is not empty, we have a WebContents // so cache the WebContent's url. If not use the cached version.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java index cd0a7f2..2db2a9e1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
@@ -84,8 +84,8 @@ */ public final boolean createTabWithWebContents(Tab parent, WebContents webContents, int parentId, TabLaunchType type) { - return createTabWithWebContents(parent, webContents, parentId, type, - webContents.getUrl()); + return createTabWithWebContents( + parent, webContents, parentId, type, webContents.getVisibleUrl()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index a301c118..5786caf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -70,6 +70,7 @@ public class VrShellDelegate implements ApplicationStatus.ActivityStateListener, View.OnSystemUiVisibilityChangeListener { private static final String TAG = "VrShellDelegate"; + // Pseudo-random number to avoid request id collisions. public static final int EXIT_VR_RESULT = 721251; @@ -168,6 +169,8 @@ private View mOverlayView; + private final VSyncEstimator mVSyncEstimator; + private static final class VrBroadcastReceiver extends BroadcastReceiver { private final WeakReference<ChromeActivity> mTargetActivity; @@ -474,6 +477,85 @@ return ChromeFeatureList.isEnabled(ChromeFeatureList.VR_SHELL); } + private class VSyncEstimator { + private static final long NANOS_PER_SECOND = 1000000000; + + private static final long VSYNC_TIMEBASE_UPDATE_DELTA = 1 * NANOS_PER_SECOND; + private static final double VSYNC_DRIFT_THRESHOLD = 1.2; + + // Estimates based on too few frames are unstable, probably anything above 2 is reasonable. + // Higher numbers will reduce how frequently we update the native vsync base/interval. + private static final int MIN_FRAME_COUNT = 5; + + private final long mReportedVSyncNanos; + private final long mMaxVSyncIntervalNanos; + private final long mMinVSyncIntervalNanos; + + private long mVSyncTimebaseNanos; + private long mVSyncIntervalNanos; + private long mVSyncIntervalMicros; + + private final FrameCallback mCallback = new FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + if (mNativeVrShellDelegate == 0) return; + Choreographer.getInstance().postFrameCallback(this); + if (mVSyncTimebaseNanos == 0) { + updateVSyncInterval(frameTimeNanos, mVSyncIntervalNanos); + return; + } + long elapsed = frameTimeNanos - mVSyncTimebaseNanos; + // If you're hitting the assert below, you probably added the callback twice. + assert elapsed != 0; + long count = Math.round(elapsed / (double) mVSyncIntervalNanos); + if (count < MIN_FRAME_COUNT) return; + long vSyncIntervalNanos = elapsed / count; + if (vSyncIntervalNanos > mMaxVSyncIntervalNanos + || vSyncIntervalNanos < mMinVSyncIntervalNanos) { + // This algorithm for computing VSync becomes unstable if it drifts too far from + // the real VSync, which shouldn't happen in practice. If this assert is getting + // hit, something has gone very wrong, but we should probably do something + // reasonable for release builds. + Log.v(TAG, "Error computing VSync interval. Resetting."); + assert false; + vSyncIntervalNanos = mReportedVSyncNanos; + } + updateVSyncInterval(frameTimeNanos, vSyncIntervalNanos); + } + }; + + public VSyncEstimator() { + Display display = ((WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay(); + mReportedVSyncNanos = (long) ((1.0d / display.getRefreshRate()) * NANOS_PER_SECOND); + mVSyncIntervalNanos = mReportedVSyncNanos; + mMaxVSyncIntervalNanos = (long) (VSYNC_DRIFT_THRESHOLD * mReportedVSyncNanos); + mMinVSyncIntervalNanos = (long) (mReportedVSyncNanos / VSYNC_DRIFT_THRESHOLD); + } + + void updateVSyncInterval(long frameTimeNanos, long vSyncIntervalNanos) { + mVSyncIntervalNanos = vSyncIntervalNanos; + long vSyncIntervalMicros = mVSyncIntervalNanos / 1000; + if (vSyncIntervalMicros == mVSyncIntervalMicros + && frameTimeNanos - mVSyncTimebaseNanos < VSYNC_TIMEBASE_UPDATE_DELTA) { + return; + } + mVSyncIntervalMicros = vSyncIntervalMicros; + mVSyncTimebaseNanos = frameTimeNanos; + + nativeUpdateVSyncInterval( + mNativeVrShellDelegate, mVSyncTimebaseNanos, mVSyncIntervalMicros); + } + + public void pause() { + Choreographer.getInstance().removeFrameCallback(mCallback); + } + + public void resume() { + Choreographer.getInstance().postFrameCallback(mCallback); + } + } + private VrShellDelegate(ChromeActivity activity, VrClassesWrapper wrapper) { mActivity = activity; mVrClassesWrapper = wrapper; @@ -485,17 +567,7 @@ mFeedbackFrequency = VrFeedbackStatus.getFeedbackFrequency(); mEnterVrHandler = new Handler(); mExpectPauseOrDonSucceeded = new Handler(); - Choreographer.getInstance().postFrameCallback(new FrameCallback() { - @Override - public void doFrame(long frameTimeNanos) { - if (mNativeVrShellDelegate == 0) return; - Display display = - ((WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay(); - nativeUpdateVSyncInterval( - mNativeVrShellDelegate, frameTimeNanos, 1.0d / display.getRefreshRate()); - } - }); + mVSyncEstimator = new VSyncEstimator(); ApplicationStatus.registerStateListenerForAllActivities(this); if (!mPaused) onResume(); } @@ -688,7 +760,10 @@ // onResume needs to be called on GvrLayout after initialization to make sure DON flow works // properly. - if (!mPaused) mVrShell.resume(); + if (!mPaused) { + mVrShell.resume(); + mVSyncEstimator.resume(); + } maybeSetPresentResult(true, donSuceeded); mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this); @@ -872,6 +947,7 @@ if (mInVr) { mVrShell.resume(); + mVSyncEstimator.resume(); } if (mDonSucceeded) { @@ -924,7 +1000,10 @@ cancelPendingVrEntry(); // We defer pausing of VrShell until the app is stopped to keep head tracking working for // as long as possible while going to daydream home. - if (mInVr) mVrShell.pause(); + if (mInVr) { + mVrShell.pause(); + mVSyncEstimator.pause(); + } if (mShowingDaydreamDoff || mProbablyInDon) return; // TODO(mthiesse): When the user resumes Chrome in a 2D context, we don't want to tear down @@ -1053,6 +1132,7 @@ restoreWindowMode(); mVrShell.pause(); + mVSyncEstimator.pause(); removeVrViews(); destroyVrShell(); if (disableVrMode) mVrClassesWrapper.setVrModeEnabled(mActivity, false); @@ -1349,8 +1429,8 @@ private static native void nativeOnLibraryAvailable(); private native void nativeSetPresentResult(long nativeVrShellDelegate, boolean result); private native void nativeDisplayActivate(long nativeVrShellDelegate); - private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, long timebaseNanos, - double intervalSeconds); + private native void nativeUpdateVSyncInterval( + long nativeVrShellDelegate, long timebaseNanos, long intervalMicros); private native void nativeOnPause(long nativeVrShellDelegate); private native void nativeOnResume(long nativeVrShellDelegate); private native void nativeUpdateNonPresentingContext(long nativeVrShellDelegate, long context);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java index fd0edbde..a811afa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java
@@ -7,7 +7,6 @@ import android.annotation.TargetApi; import android.app.ActivityManager; import android.app.ActivityManager.AppTask; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -110,21 +109,6 @@ if (data != null && TextUtils.equals(WebappActivity.WEBAPP_SCHEME, data.getScheme())) { liveWebapps.add(data.getHost()); } - - // WebappManagedActivities have titles from "WebappActivity0" through "WebappActivity9". - ComponentName component = intent.getComponent(); - if (component != null) { - String fullClassName = component.getClassName(); - int lastPeriodIndex = fullClassName.lastIndexOf("."); - if (lastPeriodIndex != -1) { - String className = fullClassName.substring(lastPeriodIndex + 1); - if (className.startsWith(WEBAPP_DIRECTORY_NAME) - && className.length() > WEBAPP_DIRECTORY_NAME.length()) { - String activityIndex = className.substring(WEBAPP_DIRECTORY_NAME.length()); - liveWebapps.add(activityIndex); - } - } - } } if (webappBaseDirectory != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index 3dd7ed9..ee14c15 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -45,6 +45,7 @@ import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.ActionModeController.ActionBarDelegate; import org.chromium.chrome.browser.toolbar.BottomToolbarPhone; @@ -241,6 +242,9 @@ /** Whether the help bubble has been shown. **/ private boolean mHasShownTextBubble; + /** Whether or not the back button was used to enter the tab switcher. */ + private boolean mBackButtonDismissesChrome; + /** * An interface defining content that can be displayed inside of the bottom sheet for Chrome * Home. @@ -484,6 +488,34 @@ } /** + * Handle a back press event. + * - If the navigation stack is empty, the sheet will be opened to the half state. + * - If the tab switcher is visible, {@link ChromeActivity} will handle the event. + * - If the sheet is open it will be closed unless it was opened by a back press. + * @return True if the sheet handled the back press. + */ + public boolean handleBackPress() { + Tab tab = getActiveTab(); + boolean consumeEvent = false; + + if (!isSheetOpen() && tab != null && !tab.canGoBack() && !isInOverviewMode() + && tab.getLaunchType() == TabLaunchType.FROM_CHROME_UI) { + mBackButtonDismissesChrome = true; + setSheetState(SHEET_STATE_HALF, true); + return true; + } else if (isSheetOpen() && !mBackButtonDismissesChrome) { + consumeEvent = true; + } + + if (getSheetState() != SHEET_STATE_PEEK) { + getBottomSheetMetrics().setSheetCloseReason(BottomSheetMetrics.CLOSED_BY_BACK_PRESS); + setSheetState(SHEET_STATE_PEEK, true); + } + + return consumeEvent; + } + + /** * Sets whether the {@link BottomSheet} and its children should react to touch events. */ public void setTouchEnabled(boolean enabled) { @@ -972,6 +1004,7 @@ private void onSheetClosed() { if (!mIsSheetOpen) return; + mBackButtonDismissesChrome = false; mIsSheetOpen = false; for (BottomSheetObserver o : mObservers) o.onSheetClosed(); announceForAccessibility(getResources().getString(R.string.bottom_sheet_closed)); @@ -1381,6 +1414,13 @@ } /** + * @return Whether or not the browser is in overview mode. + */ + private boolean isInOverviewMode() { + return mActivity != null && mActivity.isInOverviewMode(); + } + + /** * @return Whether the Google 'G' logo should be shown in the location bar. */ public boolean shouldShowGoogleGInLocationBar() { @@ -1392,16 +1432,12 @@ * mode, when "find in page" is visible, or when the toolbar is hidden. */ private boolean canMoveSheet() { - boolean isInOverviewMode = mTabModelSelector != null - && (mTabModelSelector.getCurrentTab() == null - || mTabModelSelector.getCurrentTab().getActivity().isInOverviewMode()); - if (mFindInPageView == null) mFindInPageView = findViewById(R.id.find_toolbar); boolean isFindInPageVisible = mFindInPageView != null && mFindInPageView.getVisibility() == View.VISIBLE; return !isToolbarAndroidViewHidden() - && (!isInOverviewMode || mNtpController.isShowingNewTabUi()) + && (!isInOverviewMode() || mNtpController.isShowingNewTabUi()) && !isFindInPageVisible; }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 8025440..6d29d30d 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1525,6 +1525,7 @@ "javatests/src/org/chromium/chrome/browser/physicalweb/UrlManagerTest.java", "javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java", "javatests/src/org/chromium/chrome/browser/payments/CurrencyFormatterTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java", @@ -1701,6 +1702,7 @@ "javatests/src/org/chromium/chrome/browser/widget/RadioButtonLayoutTest.java", "javatests/src/org/chromium/chrome/browser/widget/RoundedIconGeneratorTest.java", "javatests/src/org/chromium/chrome/browser/widget/ToolbarProgressBarTest.java", + "javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java", "javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentControllerTest.java", "javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserverTest.java", "javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java index 12bcd77..bc65af1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java
@@ -281,7 +281,7 @@ mActivityTestRule.getActivity() .getCurrentContentViewCore() .getWebContents() - .getUrl()); + .getLastCommittedUrl()); executeJavaScriptAndWaitForDialog("history.back();"); jsDialog = getCurrentDialog(); @@ -297,7 +297,7 @@ mActivityTestRule.getActivity() .getCurrentContentViewCore() .getWebContents() - .getUrl()); + .getLastCommittedUrl()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java index 0f73273..137cc72 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
@@ -14,7 +14,6 @@ import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; @@ -121,12 +120,9 @@ } @Test - /* @SmallTest @Feature({"Autofill"}) @RetryOnFailure - */ - @DisabledTest(message = "crbug.com/739575") public void testAddAndDeleteProfile() throws InterruptedException, ExecutionException, TimeoutException { String profileOneGUID = mHelper.setProfile(createTestProfile()); @@ -261,11 +257,8 @@ } @Test - /* @SmallTest @Feature({"Autofill"}) - */ - @DisabledTest(message = "crbug.com/739575") public void testLabels() throws InterruptedException, ExecutionException, TimeoutException { AutofillProfile profile1 = new AutofillProfile( "" /* guid */, "https://www.example.com" /* origin */, @@ -317,11 +310,8 @@ } @Test - /* @SmallTest @Feature({"Autofill"}) - */ - @DisabledTest(message = "crbug.com/739575") public void testProfilesFrecency() throws InterruptedException, ExecutionException, TimeoutException { // Create 3 profiles. @@ -447,12 +437,9 @@ } @Test - /* @SmallTest @Feature({"Autofill"}) @RetryOnFailure - */ - @DisabledTest(message = "crbug.com/739575") public void testCreditCardUseStatsSettingAndGetting() throws InterruptedException, ExecutionException, TimeoutException { String guid = mHelper.setCreditCard( @@ -500,12 +487,9 @@ } @Test - /* @SmallTest @Feature({"Autofill"}) @RetryOnFailure - */ - @DisabledTest(message = "crbug.com/739575") public void testRecordAndLogCreditCardUse() throws InterruptedException, ExecutionException, TimeoutException { String guid = mHelper.setCreditCard(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java new file mode 100644 index 0000000..7b6e847 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java
@@ -0,0 +1,238 @@ +// 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.payments; + +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.components.payments.PaymentManifestDownloader; +import org.chromium.components.payments.PaymentManifestDownloader.ManifestDownloadCallback; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; +import org.chromium.net.test.EmbeddedTestServer; + +import java.net.URI; + +/** An integration test for the payment manifest downloader. */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ + ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, +}) +@MediumTest +public class PaymentManifestDownloaderTest implements ManifestDownloadCallback { + @Rule + public ChromeActivityTestRule<ChromeActivity> mRule = + new ChromeActivityTestRule<>(ChromeActivity.class); + + private static final String PAYMENT_METHOD_MANIFEST = "{\n" + + " \"default_applications\": [\"app.json\"],\n" + + " \"supported_origins\": [\"https://alicepay.com\"]\n" + + "}\n"; + + private static final String WEB_APP_MANIFEST = "{\n" + + " \"name\": \"BobPay\",\n" + + " \"related_applications\": [{\n" + + " \"platform\": \"play\",\n" + + " \"id\": \"com.bobpay\",\n" + + " \"min_version\": \"1\",\n" + + " \"fingerprints\": [{\n" + + " \"type\": \"sha256_cert\",\n" + + " \"value\": \"59:5C:88:65:FF:C4:E8:20:CF:F7:3E:C8:64:D0" + + ":95:F0:06:19:2E:A6:7B:20:04:D1:03:07:92:E2:A5:31:67:66\"\n" + + " }]\n" + + " }]\n" + + "}\n"; + + private final PaymentManifestDownloader mDownloader = new PaymentManifestDownloader(); + private EmbeddedTestServer mServer; + private boolean mDownloadComplete; + private boolean mDownloadPaymentMethodManifestSuccess; + private boolean mDownloadWebAppManifestSuccess; + private boolean mDownloadFailure; + private String mPaymentMethodManifest; + private String mWebAppManifest; + + @Override + public void onPaymentMethodManifestDownloadSuccess(String content) { + mDownloadComplete = true; + mDownloadPaymentMethodManifestSuccess = true; + mPaymentMethodManifest = content; + } + + @Override + public void onWebAppManifestDownloadSuccess(String content) { + mDownloadComplete = true; + mDownloadWebAppManifestSuccess = true; + mWebAppManifest = content; + } + + @Override + public void onManifestDownloadFailure() { + mDownloadComplete = true; + mDownloadFailure = true; + } + + @Before + public void setUp() throws Throwable { + mRule.startMainActivityOnBlankPage(); + mServer = EmbeddedTestServer.createAndStartServer( + InstrumentationRegistry.getInstrumentation().getContext()); + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.initialize( + mRule.getActivity().getCurrentContentViewCore().getWebContents()); + mDownloader.allowHttpForTest(); + } + }); + mDownloadComplete = false; + mDownloadPaymentMethodManifestSuccess = false; + mDownloadWebAppManifestSuccess = false; + mDownloadFailure = false; + mPaymentMethodManifest = null; + mWebAppManifest = null; + } + + @After + public void tearDown() throws Throwable { + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.destroy(); + } + }); + mServer.stopAndDestroyServer(); + } + + @Test + @Feature({"Payments"}) + public void testDownloadWebAppManifest() throws Throwable { + final URI uri = new URI(mServer.getURL("/chrome/test/data/payments/app.json")); + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.downloadWebAppManifest(uri, PaymentManifestDownloaderTest.this); + } + }); + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mDownloadComplete; + } + }); + + Assert.assertTrue( + "Web app manifest should have been downloaded.", mDownloadWebAppManifestSuccess); + Assert.assertEquals(WEB_APP_MANIFEST, mWebAppManifest); + } + + @Test + @Feature({"Payments"}) + public void testUnableToDownloadWebAppManifest() throws Throwable { + final URI uri = new URI(mServer.getURL("/no-such-app.json")); + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.downloadWebAppManifest(uri, PaymentManifestDownloaderTest.this); + } + }); + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mDownloadComplete; + } + }); + + Assert.assertTrue("Web app manifest should not have been downloaded.", mDownloadFailure); + } + + @Test + @Feature({"Payments"}) + public void testDownloadPaymentMethodManifest() throws Throwable { + final URI uri = new URI(mServer.getURL("/chrome/test/data/payments/webpay")); + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.downloadPaymentMethodManifest(uri, PaymentManifestDownloaderTest.this); + } + }); + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mDownloadComplete; + } + }); + + Assert.assertTrue("Payment method manifest should have been downloaded.", + mDownloadPaymentMethodManifestSuccess); + Assert.assertEquals(PAYMENT_METHOD_MANIFEST, mPaymentMethodManifest); + } + + @Test + @Feature({"Payments"}) + public void testUnableToDownloadPaymentMethodManifest() throws Throwable { + final URI uri = new URI(mServer.getURL("/no-such-payment-method-name")); + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.downloadPaymentMethodManifest(uri, PaymentManifestDownloaderTest.this); + } + }); + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mDownloadComplete; + } + }); + + Assert.assertTrue( + "Payment method manifest should have not have been downloaded.", mDownloadFailure); + } + + @Test + @Feature({"Payments"}) + public void testSeveralDownloadsAtOnce() throws Throwable { + final URI paymentMethodUri1 = new URI(mServer.getURL("/no-such-payment-method-name")); + final URI paymentMethodUri2 = new URI(mServer.getURL("/chrome/test/data/payments/webpay")); + final URI webAppUri1 = new URI(mServer.getURL("/no-such-app.json")); + final URI webAppUri2 = new URI(mServer.getURL("/chrome/test/data/payments/app.json")); + mRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mDownloader.downloadPaymentMethodManifest( + paymentMethodUri1, PaymentManifestDownloaderTest.this); + mDownloader.downloadPaymentMethodManifest( + paymentMethodUri2, PaymentManifestDownloaderTest.this); + mDownloader.downloadWebAppManifest(webAppUri1, PaymentManifestDownloaderTest.this); + mDownloader.downloadWebAppManifest(webAppUri2, PaymentManifestDownloaderTest.this); + } + }); + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mDownloadWebAppManifestSuccess && mDownloadPaymentMethodManifestSuccess + && mDownloadFailure; + } + }); + + Assert.assertEquals(PAYMENT_METHOD_MANIFEST, mPaymentMethodManifest); + Assert.assertEquals(WEB_APP_MANIFEST, mWebAppManifest); + } +} \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java index 475fe80..5302797a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
@@ -5,6 +5,8 @@ package org.chromium.chrome.browser.payments; import static org.chromium.chrome.browser.payments.PaymentRequestTestRule.DELAYED_RESPONSE; +import static org.chromium.chrome.browser.payments.PaymentRequestTestRule.HAVE_INSTRUMENTS; +import static org.chromium.chrome.browser.payments.PaymentRequestTestRule.IMMEDIATE_RESPONSE; import static org.chromium.chrome.browser.payments.PaymentRequestTestRule.NO_INSTRUMENTS; import android.content.DialogInterface; @@ -45,7 +47,9 @@ new PaymentRequestTestRule("payment_request_metrics_test.html", this); @Override - public void onMainActivityStarted() + public void onMainActivityStarted() {} + + private void createTestData() throws InterruptedException, ExecutionException, TimeoutException { AutofillTestHelper mHelper = new AutofillTestHelper(); // The user has a shipping address and a credit card associated with that address on disk. @@ -72,6 +76,8 @@ @Feature({"Payments"}) public void testNumberOfSuggestionsShown_ShippingAddress_Completed() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickAndWait( @@ -106,6 +112,8 @@ @Feature({"Payments"}) public void testNumberOfSuggestionsShown_ShippingAddress_AbortedByUser() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Cancel the payment request. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickAndWait( @@ -139,6 +147,8 @@ @Feature({"Payments"}) public void testNumberOfSelectionEdits_ShippingAddress_Completed() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickInShippingAddressAndWait( @@ -183,6 +193,8 @@ @Feature({"Payments"}) public void testNumberOfSelectionAdds_ShippingAddress_Completed() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickInShippingAddressAndWait( @@ -230,6 +242,8 @@ @Feature({"Payments"}) public void testNumberOfSuggestionsShown_CreditCards_Completed() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickAndWait( @@ -264,6 +278,8 @@ @Feature({"Payments"}) public void testNumberOfSuggestionsShown_CreditCards_AbortedByUser() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Cancel the payment request. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickAndWait( @@ -297,6 +313,8 @@ @Feature({"Payments"}) public void testNumberOfSelectionAdds_CreditCards_Completed() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); @@ -343,6 +361,8 @@ @Feature({"Payments"}) public void testNoContactInfoHistogram() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickAndWait( @@ -375,6 +395,8 @@ @MediumTest @Feature({"Payments"}) public void testTwoTimes() throws InterruptedException, ExecutionException, TimeoutException { + createTestData(); + // Complete a Payment Request with a credit card. mPaymentRequestTestRule.triggerUIAndWait("ccBuy", mPaymentRequestTestRule.getReadyToPay()); mPaymentRequestTestRule.clickAndWait( @@ -453,4 +475,231 @@ RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.Completed", 2)); } + + /** + * Expect that the UserHadInitialFormOfPayment histogram gets logged properly when the user has + * at least one credit card on file. + */ + @Test + @MediumTest + @Feature({"Payments"}) + public void testUserHadInitialFormOfPayment_AcceptsCardsAndApps_UserHasOnlyCard() + throws InterruptedException, ExecutionException, TimeoutException { + // Add an address and a credit card on file. + AutofillTestHelper mHelper = new AutofillTestHelper(); + String mBillingAddressId = mHelper.setProfile(new AutofillProfile("", "https://example.com", + true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", + "US", "650-253-0000", "", "en-US")); + mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe", + "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card, + CardType.UNKNOWN, mBillingAddressId, "" /* serverId */)); + + mPaymentRequestTestRule.triggerUIAndWait( + "cardsAndBobPayBuy", mPaymentRequestTestRule.getReadyToPay()); + + // The user cancels the Payment Request (trigger the logs). + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); + + // Make sure that the fact that the user had a form of payment was recorded. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", + CompletionStatus.USER_ABORTED)); + + // Make sure the opposite metric has no logs. + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion")); + } + + /** + * Expect that the UserHadInitialFormOfPayment histogram gets logged properly when the user has + * at least one payment app on file. + */ + @Test + @MediumTest + @Feature({"Payments"}) + public void testUserHadInitialFormOfPayment_AcceptsCardsAndApps_UserHasOnlyPaymentApp() + throws InterruptedException, ExecutionException, TimeoutException { + // Add an address and a payment app on file. + AutofillTestHelper mHelper = new AutofillTestHelper(); + mHelper.setProfile(new AutofillProfile("", "https://example.com", true, "Jon Doe", "Google", + "340 Main St", "CA", "Los Angeles", "", "90291", "", "US", "650-253-0000", "", + "en-US")); + mPaymentRequestTestRule.installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); + + mPaymentRequestTestRule.triggerUIAndWait( + "cardsAndBobPayBuy", mPaymentRequestTestRule.getReadyToPay()); + + // The user cancels the Payment Request (trigger the logs). + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); + + // Make sure that the fact that the user had a form of payment was recorded. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", + CompletionStatus.USER_ABORTED)); + + // Make sure the opposite metric has no logs. + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion")); + } + + /** + * Expect that the UserHadInitialFormOfPayment histogram gets logged properly when the user has + * at both a card and a payment app on file. + */ + @Test + @MediumTest + @Feature({"Payments"}) + public void testUserHadInitialFormOfPayment_AcceptsCardsAndApps_UserHasCardAndPaymentApp() + throws InterruptedException, ExecutionException, TimeoutException { + // Add an address, a credit card and a payment app on file. + AutofillTestHelper mHelper = new AutofillTestHelper(); + String mBillingAddressId = mHelper.setProfile(new AutofillProfile("", "https://example.com", + true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", + "US", "650-253-0000", "", "en-US")); + mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe", + "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card, + CardType.UNKNOWN, mBillingAddressId, "" /* serverId */)); + mPaymentRequestTestRule.installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); + + mPaymentRequestTestRule.triggerUIAndWait( + "cardsAndBobPayBuy", mPaymentRequestTestRule.getReadyToPay()); + + // The user cancels the Payment Request (trigger the logs). + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); + + // Make sure that the fact that the user had a form of payment was recorded. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", + CompletionStatus.USER_ABORTED)); + + // Make sure the opposite metric has no logs. + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion")); + } + + /** + * Expect that the UserDidNotHaveInitialFormOfPayment histogram gets logged properly when the + * user has no form of payment on file. + */ + @Test + @MediumTest + @Feature({"Payments"}) + public void testUserHadInitialFormOfPayment_AcceptsCardsAndApps_UserHasNoCardOrPaymentApp() + throws InterruptedException, ExecutionException, TimeoutException { + // Add an address on file. + new AutofillTestHelper().setProfile(new AutofillProfile("", "https://example.com", true, + "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", "US", + "650-253-0000", "", "en-US")); + + mPaymentRequestTestRule.triggerUIAndWait( + "cardsAndBobPayBuy", mPaymentRequestTestRule.getReadyForInput()); + + // The user cancels the Payment Request (trigger the logs). + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); + + // Make sure that the fact that the user had no form of payment was recorded. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + CompletionStatus.USER_ABORTED)); + + // Make sure the opposite metric has no logs. + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion")); + } + + /** + * Expect that the UserDidNotHaveInitialFormOfPayment histogram gets logged properly when the + * user has a payment app but the merchant only accepts credit cards. + */ + @Test + @MediumTest + @Feature({"Payments"}) + public void testUserHadInitialFormOfPayment_AcceptsCards_UserHasOnlyApp() + throws InterruptedException, ExecutionException, TimeoutException { + // Add an address and a payment app on file. + AutofillTestHelper mHelper = new AutofillTestHelper(); + mHelper.setProfile(new AutofillProfile("", "https://example.com", true, "Jon Doe", "Google", + "340 Main St", "CA", "Los Angeles", "", "90291", "", "US", "650-253-0000", "", + "en-US")); + mPaymentRequestTestRule.installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); + + mPaymentRequestTestRule.triggerUIAndWait( + "ccBuy", mPaymentRequestTestRule.getReadyForInput()); + + // The user cancels the Payment Request (trigger the logs). + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); + + // Make sure that the fact that the user had no form of payment was recorded. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + CompletionStatus.USER_ABORTED)); + + // Make sure the opposite metric has no logs. + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion")); + } + + /** + * Expect that the UserDidNotHaveInitialFormOfPayment histogram gets logged properly when the + * user has a payment app but the merchant only accepts credit cards. + */ + @Test + @MediumTest + @Feature({"Payments"}) + public void testUserHadInitialFormOfPayment_AcceptsCards_UserHasOnlyUnsupportedNetwork() + throws InterruptedException, ExecutionException, TimeoutException { + // Add an address and a card from an unsupported network on file. + AutofillTestHelper mHelper = new AutofillTestHelper(); + String mBillingAddressId = mHelper.setProfile(new AutofillProfile("", "https://example.com", + true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", + "US", "650-253-0000", "", "en-US")); + mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe", + "378282246310005", "1111", "12", "2050", "amex", R.drawable.visa_card, + CardType.UNKNOWN, mBillingAddressId, "" /* serverId */)); + + mPaymentRequestTestRule.triggerUIAndWait( + "ccBuy", mPaymentRequestTestRule.getReadyForInput()); + + // The user cancels the Payment Request (trigger the logs). + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); + + // Make sure that the fact that the user had no form of payment was recorded. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + CompletionStatus.USER_ABORTED)); + + // Make sure the opposite metric has no logs. + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion")); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ClearAppDataTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ClearAppDataTestRule.java index 76e2e90..e8860f8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ClearAppDataTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ClearAppDataTestRule.java
@@ -23,7 +23,9 @@ return new Statement() { @Override public void evaluate() throws Throwable { - ApplicationData.clearAppData(InstrumentationRegistry.getContext()); + ApplicationData.clearAppData( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + base.evaluate(); } }; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java new file mode 100644 index 0000000..7320f19 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
@@ -0,0 +1,282 @@ +// 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.widget.bottomsheet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_PHONE; + +import android.content.Intent; +import android.net.Uri; +import android.provider.Browser; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; +import org.chromium.chrome.test.BottomSheetTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.ChromeTabUtils; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; +import org.chromium.net.test.EmbeddedTestServer; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * Tests the behavior of the bottom sheet when used with the back button. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({BottomSheetTestRule.ENABLE_CHROME_HOME, + ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + BottomSheetTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) +@Restriction(RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones +public class BottomSheetBackBehaviorTest { + private static final String TEST_PAGE = "/chrome/test/data/android/simple.html"; + + private BottomSheet mBottomSheet; + private ChromeTabbedActivity mActivity; + private LayoutManagerChrome mLayoutManager; + + @Rule + public BottomSheetTestRule mBottomSheetTestRule = new BottomSheetTestRule(); + + @Before + public void setUp() throws Exception { + mBottomSheetTestRule.startMainActivityOnBlankPage(); + mBottomSheet = mBottomSheetTestRule.getBottomSheet(); + mActivity = mBottomSheetTestRule.getActivity(); + mBottomSheetTestRule.setSheetState(BottomSheet.SHEET_STATE_PEEK, false); + mLayoutManager = mActivity.getLayoutManager(); + } + + @Test + @SmallTest + public void testBackButton_sheetOpen() { + mBottomSheetTestRule.setSheetState(BottomSheet.SHEET_STATE_HALF, false); + + pressBackButton(); + endBottomSheetAnimations(); + + assertFalse("Overview mode should not be showing.", mLayoutManager.overviewVisible()); + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + } + + @Test + @SmallTest + public void testBackButton_tabSwitcher() throws InterruptedException, TimeoutException { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mLayoutManager.showOverview(false); + } + }); + + assertTrue("Overview mode should be showing.", mLayoutManager.overviewVisible()); + + pressBackButton(); + endBottomSheetAnimations(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mLayoutManager.getActiveLayout().finishAnimationsForTests(); + } + }); + + assertFalse("Overview mode should not be showing.", mLayoutManager.overviewVisible()); + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + } + + @Test + @SmallTest + public void testBackButton_backFromInternalNewTab() + throws ExecutionException, InterruptedException, TimeoutException { + Tab tab = launchNewTabFromChrome("about:blank"); + + assertEquals("Tab should be on about:blank.", "about:blank", tab.getUrl()); + + // Back button press should open the bottom sheet since backward navigation is not + // possible. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("The bottom sheet should be at half height.", BottomSheet.SHEET_STATE_HALF, + mBottomSheet.getSheetState()); + assertFalse("Overview mode should not be showing.", mLayoutManager.overviewVisible()); + + // Final back press should close the sheet and chrome. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + assertFalse("Chrome should no longer have focus.", mActivity.hasWindowFocus()); + } + + @Test + @SmallTest + public void testBackButton_backFromInternalNewTab_sheetOpen() + throws ExecutionException, InterruptedException, TimeoutException { + Tab tab = launchNewTabFromChrome("about:blank"); + + assertEquals("Tab should be on about:blank.", "about:blank", tab.getUrl()); + + mBottomSheetTestRule.setSheetState(BottomSheet.SHEET_STATE_HALF, false); + + // Back button should close the sheet but not send Chrome to the background. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + assertTrue("Chrome should have focus.", mActivity.hasWindowFocus()); + + // Back button press should open the bottom sheet since backward navigation is not + // possible. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("The bottom sheet should be at half height.", BottomSheet.SHEET_STATE_HALF, + mBottomSheet.getSheetState()); + assertFalse("Overview mode should not be showing.", mLayoutManager.overviewVisible()); + + // Final back press should close the sheet and chrome. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + assertFalse("Chrome should no longer have focus.", mActivity.hasWindowFocus()); + } + + @Test + @SmallTest + public void testBackButton_backWithNavigation() + throws ExecutionException, InterruptedException, TimeoutException { + final Tab tab = mBottomSheet.getActiveTab(); + + EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer( + InstrumentationRegistry.getInstrumentation().getContext()); + + String testUrl = testServer.getURL(TEST_PAGE); + ChromeTabUtils.loadUrlOnUiThread(tab, testUrl); + ChromeTabUtils.waitForTabPageLoaded(tab, testUrl); + + mBottomSheetTestRule.setSheetState(BottomSheet.SHEET_STATE_HALF, false); + + // Back button should close the bottom sheet. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("Tab should be on the test page.", testUrl, tab.getUrl()); + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + assertFalse("Overview mode should not be showing.", mLayoutManager.overviewVisible()); + + // Next back button press should navigate back. + pressBackButton(); + endBottomSheetAnimations(); + ChromeTabUtils.waitForTabPageLoaded(tab, "about:blank"); + + assertEquals("Tab should be on about:blank.", "about:blank", tab.getUrl()); + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + assertFalse("Overview mode should not be showing.", mLayoutManager.overviewVisible()); + } + + @Test + @SmallTest + public void testBackButton_backFromExternalNewTab() + throws InterruptedException, TimeoutException { + EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer( + InstrumentationRegistry.getInstrumentation().getContext()); + launchNewTabFromExternalApp(testServer.getURL(TEST_PAGE)); + + // Back button should send Chrome to the background. + pressBackButton(); + endBottomSheetAnimations(); + + assertEquals("The bottom sheet should be peeking.", BottomSheet.SHEET_STATE_PEEK, + mBottomSheet.getSheetState()); + assertFalse("Chrome should no longer have focus.", mActivity.hasWindowFocus()); + } + + /** + * Launch a new tab from an "external" app. + * @param url The URL to launch in the tab. + */ + private void launchNewTabFromExternalApp(String url) throws InterruptedException { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, "externalApp"); + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); + intent.setData(Uri.parse(url)); + + final Tab originalTab = mActivity.getActivityTab(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mActivity.onNewIntent(intent); + } + }); + CriteriaHelper.pollUiThread(new Criteria("Failed to select different tab") { + @Override + public boolean isSatisfied() { + return mActivity.getActivityTab() != originalTab; + } + }); + ChromeTabUtils.waitForTabPageLoaded(mActivity.getActivityTab(), url); + } + + /** + * Launch a new tab from Chrome internally. + * @param url The URL to launch in the tab. + */ + private Tab launchNewTabFromChrome(final String url) throws ExecutionException { + return ThreadUtils.runOnUiThreadBlocking(new Callable<Tab>() { + @Override + public Tab call() { + return mActivity.getTabCreator(false).launchUrl( + url, TabLaunchType.FROM_CHROME_UI); + } + }); + } + + /** Notify the activity that the hardware back button was pressed. */ + private void pressBackButton() { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mActivity.onBackPressed(); + } + }); + } + + /** End bottom sheet animations. */ + private void endBottomSheetAnimations() { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mBottomSheet.endAnimationsForTests(); + } + }); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java index 2f55f59a0d..1bb462ca 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
@@ -289,7 +289,10 @@ Mockito.when(packageManagerDelegate.getPackageInfoWithSignatures("com.bobpay.app")) .thenReturn(bobPayPackageInfo); - PaymentManifestDownloader downloader = new PaymentManifestDownloader(null) { + PaymentManifestDownloader downloader = new PaymentManifestDownloader() { + @Override + public void initialize(WebContents webContents) {} + @Override public void downloadPaymentMethodManifest(URI uri, ManifestDownloadCallback callback) { callback.onPaymentMethodManifestDownloadSuccess("some content here"); @@ -299,6 +302,9 @@ public void downloadWebAppManifest(URI uri, ManifestDownloadCallback callback) { callback.onWebAppManifestDownloadSuccess("some content here"); } + + @Override + public void destroy() {} }; PaymentManifestParser parser = new PaymentManifestParser() {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/payments/PaymentManifestVerifierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/payments/PaymentManifestVerifierTest.java index dbe7fe3..806887bf 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/payments/PaymentManifestVerifierTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/payments/PaymentManifestVerifierTest.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.payments.PaymentManifestVerifier.ManifestVerifyCallback; import org.chromium.components.payments.PaymentManifestDownloader; import org.chromium.components.payments.PaymentManifestParser; +import org.chromium.content_public.browser.WebContents; import org.chromium.payments.mojom.WebAppManifestSection; import java.net.URI; @@ -55,7 +56,10 @@ mMatchingApps.add(mAlicePay); mMatchingApps.add(mBobPay); - mDownloader = new PaymentManifestDownloader(null) { + mDownloader = new PaymentManifestDownloader() { + @Override + public void initialize(WebContents webContents) {} + @Override public void downloadPaymentMethodManifest(URI uri, ManifestDownloadCallback callback) { callback.onPaymentMethodManifestDownloadSuccess("some content here"); @@ -65,6 +69,9 @@ public void downloadWebAppManifest(URI uri, ManifestDownloadCallback callback) { callback.onWebAppManifestDownloadSuccess("some content here"); } + + @Override + public void destroy() {} }; mWebDataService = Mockito.mock(PaymentManifestWebDataService.class); @@ -122,12 +129,18 @@ @Test public void testUnableToDownloadPaymentMethodManifest() { PaymentManifestVerifier verifier = new PaymentManifestVerifier( - mMethodName, mMatchingApps, mWebDataService, new PaymentManifestDownloader(null) { + mMethodName, mMatchingApps, mWebDataService, new PaymentManifestDownloader() { + @Override + public void initialize(WebContents webContents) {} + @Override public void downloadPaymentMethodManifest( URI uri, ManifestDownloadCallback callback) { callback.onManifestDownloadFailure(); } + + @Override + public void destroy() {} }, mParser, mPackageManagerDelegate, mCallback); verifier.verify(); @@ -138,7 +151,10 @@ @Test public void testUnableToDownloadWebAppManifest() { PaymentManifestVerifier verifier = new PaymentManifestVerifier( - mMethodName, mMatchingApps, mWebDataService, new PaymentManifestDownloader(null) { + mMethodName, mMatchingApps, mWebDataService, new PaymentManifestDownloader() { + @Override + public void initialize(WebContents webContents) {} + @Override public void downloadPaymentMethodManifest( URI uri, ManifestDownloadCallback callback) { @@ -149,6 +165,9 @@ public void downloadWebAppManifest(URI uri, ManifestDownloadCallback callback) { callback.onManifestDownloadFailure(); } + + @Override + public void destroy() {} }, mParser, mPackageManagerDelegate, mCallback); verifier.verify(); @@ -220,9 +239,6 @@ private class CountingDownloader extends PaymentManifestDownloader { public int mDownloadWebAppManifestCounter; - public CountingDownloader() { - super(null); - } } /** If a single web app manifest fails to download, all downloads should be aborted. */
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index ef2019ff..88db55f1 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -568,8 +568,6 @@ "mac/security_wrappers.h", "media/cast_remoting_connector.cc", "media/cast_remoting_connector.h", - "media/cast_remoting_connector_messaging.cc", - "media/cast_remoting_connector_messaging.h", "media/cast_remoting_sender.cc", "media/cast_remoting_sender.h", "media/media_access_handler.cc", @@ -847,6 +845,8 @@ "page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h", "page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc", "page_load_metrics/observers/loading_predictor_page_load_metrics_observer.h", + "page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc", + "page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h", "page_load_metrics/observers/lofi_page_load_metrics_observer.cc", "page_load_metrics/observers/lofi_page_load_metrics_observer.h", "page_load_metrics/observers/media_page_load_metrics_observer.cc", @@ -1635,6 +1635,7 @@ "//media/cast:net", "//media/midi", "//media/mojo:features", + "//media/mojo/interfaces:mirror_service_remoting", "//media/mojo/interfaces:remoting", "//mojo/common", "//mojo/edk/system",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d0e8a37..0e45042 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -339,6 +339,9 @@ switches::reader_mode_heuristics::kAlwaysTrue}, {flag_descriptions::kReaderModeHeuristicsAlwaysOff, switches::kReaderModeHeuristics, switches::reader_mode_heuristics::kNone}, + {flag_descriptions::kReaderModeHeuristicsAllArticles, + switches::kReaderModeHeuristics, + switches::reader_mode_heuristics::kAllArticles}, }; const FeatureEntry::Choice kChromeHomeSwipeLogicChoices[] = { @@ -2413,11 +2416,6 @@ ntp_snippets::kArticleSuggestionsFeature, kRemoteSuggestionsFeatureVariations, ntp_snippets::kArticleSuggestionsFeature.name)}, - {"enable-ntp-recent-offline-tab-suggestions", - flag_descriptions::kEnableNtpRecentOfflineTabSuggestionsName, - flag_descriptions::kEnableNtpRecentOfflineTabSuggestionsDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(ntp_snippets::kRecentOfflineTabSuggestionsFeature)}, {"enable-ntp-asset-download-suggestions", flag_descriptions::kEnableNtpAssetDownloadSuggestionsName, flag_descriptions::kEnableNtpAssetDownloadSuggestionsDescription, @@ -2432,11 +2430,6 @@ flag_descriptions::kEnableNtpBookmarkSuggestionsName, flag_descriptions::kEnableNtpBookmarkSuggestionsDescription, kOsAndroid, FEATURE_VALUE_TYPE(ntp_snippets::kBookmarkSuggestionsFeature)}, - {"enable-ntp-physical-web-page-suggestions", - flag_descriptions::kEnableNtpPhysicalWebPageSuggestionsName, - flag_descriptions::kEnableNtpPhysicalWebPageSuggestionsDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(ntp_snippets::kPhysicalWebPageSuggestionsFeature)}, {"enable-ntp-foreign-sessions-suggestions", flag_descriptions::kEnableNtpForeignSessionsSuggestionsName, flag_descriptions::kEnableNtpForeignSessionsSuggestionsDescription, @@ -2893,6 +2886,12 @@ flag_descriptions::kOffMainThreadFetchDescription, kOsAll, FEATURE_VALUE_TYPE(features::kOffMainThreadFetch)}, + {"enable-speculative-service-worker-start-on-query-input", + flag_descriptions::kSpeculativeServiceWorkerStartOnQueryInputName, + flag_descriptions::kSpeculativeServiceWorkerStartOnQueryInputDescription, + kOsAll, + FEATURE_VALUE_TYPE(omnibox::kSpeculativeServiceWorkerStartOnQueryInput)}, + #if defined(OS_MACOSX) {"tab-strip-keyboard-focus", flag_descriptions::kTabStripKeyboardFocusName, flag_descriptions::kTabStripKeyboardFocusDescription, kOsMac,
diff --git a/chrome/browser/android/logo_service.cc b/chrome/browser/android/logo_service.cc index 1e007e36..c2fd971e 100644 --- a/chrome/browser/android/logo_service.cc +++ b/chrome/browser/android/logo_service.cc
@@ -7,8 +7,6 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/image_decoder.h" #include "chrome/browser/profiles/profile.h" @@ -52,9 +50,10 @@ // If the ImageDecoder crashes or otherwise never completes, call // OnImageDecodeTimedOut() eventually to ensure that image_decoded_callback_ // is run. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&LogoDecoderDelegate::OnDecodeImageFailed, - weak_ptr_factory_.GetWeakPtr()), + task_runner()->PostDelayedTask( + FROM_HERE, + base::Bind(&LogoDecoderDelegate::OnDecodeImageFailed, + weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds)); } @@ -87,9 +86,10 @@ void DecodeUntrustedImage( const scoped_refptr<base::RefCountedString>& encoded_image, base::Callback<void(const SkBitmap&)> image_decoded_callback) override { - LogoDecoderDelegate* delegate = - new LogoDecoderDelegate(image_decoded_callback); - ImageDecoder::Start(delegate, encoded_image->data()); + // TODO(bauerb): Switch to the components/image_fetcher implementation. + auto delegate = + base::MakeUnique<LogoDecoderDelegate>(image_decoded_callback); + ImageDecoder::Start(delegate.release(), encoded_image->data()); } private: @@ -136,9 +136,7 @@ if (!logo_tracker_) { logo_tracker_ = base::MakeUnique<LogoTracker>( profile_->GetPath().Append(kCachedLogoDirectory), - BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE), - BrowserThread::GetBlockingPool(), profile_->GetRequestContext(), - base::MakeUnique<ChromeLogoDelegate>()); + profile_->GetRequestContext(), base::MakeUnique<ChromeLogoDelegate>()); } GURL url = use_fixed_logo ? logo_url : GetGoogleDoodleURL(profile_);
diff --git a/chrome/browser/android/vr_shell/ui_elements/textured_element.cc b/chrome/browser/android/vr_shell/ui_elements/textured_element.cc index e0a7a16..afe2ae8 100644 --- a/chrome/browser/android/vr_shell/ui_elements/textured_element.cc +++ b/chrome/browser/android/vr_shell/ui_elements/textured_element.cc
@@ -29,7 +29,7 @@ } void TexturedElement::UpdateTexture() { - if (!initialized_ || !GetTexture()->dirty()) + if (!initialized_ || !GetTexture()->dirty() || !IsVisible()) return; sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( texture_size_.width(), texture_size_.height()); @@ -50,6 +50,7 @@ gfx::Transform view_proj_matrix) const { if (!initialized_) return; + DCHECK(!GetTexture()->dirty()); gfx::SizeF drawn_size = GetTexture()->GetDrawnSize(); gfx::RectF copy_rect(0, 0, drawn_size.width() / texture_size_.width(), drawn_size.height() / texture_size_.height()); @@ -77,4 +78,8 @@ UpdateTexture(); } +void TexturedElement::OnBeginFrame(const base::TimeTicks& begin_frame_time) { + UpdateTexture(); +} + } // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/textured_element.h b/chrome/browser/android/vr_shell/ui_elements/textured_element.h index f3e1411..3c009a0 100644 --- a/chrome/browser/android/vr_shell/ui_elements/textured_element.h +++ b/chrome/browser/android/vr_shell/ui_elements/textured_element.h
@@ -30,6 +30,8 @@ void Render(UiElementRenderer* renderer, gfx::Transform view_proj_matrix) const final; + void OnBeginFrame(const base::TimeTicks& begin_frame_time) override; + protected: virtual UiTexture* GetTexture() const = 0; virtual void UpdateTexture();
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc index b659625..5da786a 100644 --- a/chrome/browser/android/vr_shell/vr_shell.cc +++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -595,13 +595,13 @@ UiUnsupportedMode::kCount); } -void VrShell::UpdateVSyncInterval(int64_t timebase_nanos, - double interval_seconds) { +void VrShell::UpdateVSyncInterval(base::TimeTicks vsync_timebase, + base::TimeDelta vsync_interval) { PollMediaAccessFlag(); WaitForGlThread(); PostToGlThread(FROM_HERE, base::Bind(&VrShellGl::UpdateVSyncInterval, gl_thread_->GetVrShellGl(), - timebase_nanos, interval_seconds)); + vsync_timebase, vsync_interval)); } void VrShell::PollMediaAccessFlag() {
diff --git a/chrome/browser/android/vr_shell/vr_shell.h b/chrome/browser/android/vr_shell/vr_shell.h index df45efc..fc72930 100644 --- a/chrome/browser/android/vr_shell/vr_shell.h +++ b/chrome/browser/android/vr_shell/vr_shell.h
@@ -190,8 +190,8 @@ // device::GvrDelegate implementation. void SetWebVRSecureOrigin(bool secure_origin) override; - void UpdateVSyncInterval(int64_t timebase_nanos, - double interval_seconds) override; + void UpdateVSyncInterval(base::TimeTicks vsync_timebase, + base::TimeDelta vsync_interval) override; void CreateVRDisplayInfo( const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, uint32_t device_id) override;
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.cc b/chrome/browser/android/vr_shell/vr_shell_delegate.cc index 17acec9..1453d8e7 100644 --- a/chrome/browser/android/vr_shell/vr_shell_delegate.cc +++ b/chrome/browser/android/vr_shell/vr_shell_delegate.cc
@@ -57,8 +57,9 @@ if (device_provider_) { device_provider_->Device()->OnDelegateChanged(); } - - gvr_delegate_->UpdateVSyncInterval(timebase_nanos_, interval_seconds_); + if (vsync_timebase_ != base::TimeTicks()) { + gvr_delegate_->UpdateVSyncInterval(vsync_timebase_, vsync_interval_); + } if (pending_successful_present_request_) { gvr_delegate_->ConnectPresentingService( @@ -114,11 +115,12 @@ void VrShellDelegate::UpdateVSyncInterval(JNIEnv* env, const JavaParamRef<jobject>& obj, jlong timebase_nanos, - jdouble interval_seconds) { - timebase_nanos_ = timebase_nanos; - interval_seconds_ = interval_seconds; + jlong interval_micros) { + vsync_timebase_ = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(timebase_nanos / 1000); + vsync_interval_ = base::TimeDelta::FromMicroseconds(interval_micros); if (gvr_delegate_) { - gvr_delegate_->UpdateVSyncInterval(timebase_nanos_, interval_seconds_); + gvr_delegate_->UpdateVSyncInterval(vsync_timebase_, vsync_interval_); } }
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.h b/chrome/browser/android/vr_shell/vr_shell_delegate.h index 013e8e4..e5ca2c4c 100644 --- a/chrome/browser/android/vr_shell/vr_shell_delegate.h +++ b/chrome/browser/android/vr_shell/vr_shell_delegate.h
@@ -46,7 +46,7 @@ void UpdateVSyncInterval(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jlong timebase_nanos, - jdouble interval_seconds); + jlong interval_micros); void OnPause(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void UpdateNonPresentingContext( @@ -84,8 +84,8 @@ device::GvrDeviceProvider* device_provider_ = nullptr; device::GvrDelegate* gvr_delegate_ = nullptr; base::Callback<void(bool)> present_callback_; - int64_t timebase_nanos_ = 0; - double interval_seconds_ = 0; + base::TimeTicks vsync_timebase_; + base::TimeDelta vsync_interval_; device::mojom::VRSubmitFrameClientPtr submit_client_; device::mojom::VRPresentationProviderRequest presentation_provider_request_; bool pending_successful_present_request_ = false;
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index 63222e6..bc91a39 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -392,7 +392,6 @@ void VrShellGl::OnContentFrameAvailable() { content_surface_texture_->UpdateTexImage(); - received_frame_ = true; } void VrShellGl::OnWebVRFrameAvailable() { @@ -1287,25 +1286,23 @@ OnWebVRFrameAvailable(); } - base::TimeTicks now = base::TimeTicks::Now(); - base::TimeTicks target; - // Don't send VSyncs until we have a timebase/interval. if (vsync_interval_.is_zero()) return; + base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks target; target = now + vsync_interval_; int64_t intervals = (target - vsync_timebase_) / vsync_interval_; target = vsync_timebase_ + intervals * vsync_interval_; task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), target - now); - - base::TimeDelta time = intervals * vsync_interval_; + base::TimeDelta current = target - vsync_interval_ - base::TimeTicks(); if (!callback_.is_null()) { - SendVSync(time, base::ResetAndReturn(&callback_)); + SendVSync(current, base::ResetAndReturn(&callback_)); } else { pending_vsync_ = true; - pending_time_ = time; + pending_time_ = current; } if (!ShouldDrawWebVr()) { DrawFrame(-1); @@ -1330,13 +1327,15 @@ SendVSync(pending_time_, std::move(callback)); } -void VrShellGl::UpdateVSyncInterval(int64_t timebase_nanos, - double interval_seconds) { - vsync_timebase_ = base::TimeTicks(); - vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); - vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); - vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); - OnVSync(); +void VrShellGl::UpdateVSyncInterval(base::TimeTicks vsync_timebase, + base::TimeDelta vsync_interval) { + bool needs_init = vsync_timebase_ == base::TimeTicks(); + vsync_timebase_ = vsync_timebase; + vsync_interval_ = vsync_interval; + if (needs_init) { + vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); + OnVSync(); + } } void VrShellGl::ForceExitVr() {
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h index 802d24b..8977e81 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.h +++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -100,7 +100,8 @@ void SetControllerModel(std::unique_ptr<VrControllerModel> model); - void UpdateVSyncInterval(int64_t timebase_nanos, double interval_seconds); + void UpdateVSyncInterval(base::TimeTicks vsync_timebase, + base::TimeDelta vsync_interval); void CreateVRDisplayInfo( const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, @@ -259,7 +260,6 @@ base::TimeDelta pending_time_; bool pending_vsync_ = false; GetVSyncCallback callback_; - bool received_frame_ = false; mojo::Binding<device::mojom::VRPresentationProvider> binding_; device::mojom::VRSubmitFrameClientPtr submit_client_;
diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc index 795186d..deff8885 100644 --- a/chrome/browser/autocomplete/autocomplete_browsertest.cc +++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc
@@ -111,14 +111,14 @@ EXPECT_FALSE(location_bar->GetDestinationURL().is_valid()); EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText()); - EXPECT_TRUE(omnibox_view->IsSelectAll()); + EXPECT_FALSE(omnibox_view->IsSelectAll()); omnibox_view->SetUserText(base::ASCIIToUTF16("chrome")); location_bar->Revert(); EXPECT_FALSE(location_bar->GetDestinationURL().is_valid()); EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText()); - EXPECT_TRUE(omnibox_view->IsSelectAll()); + EXPECT_FALSE(omnibox_view->IsSelectAll()); } // Autocomplete test is flaky on ChromeOS. @@ -163,7 +163,7 @@ location_bar->Revert(); EXPECT_FALSE(location_bar->GetDestinationURL().is_valid()); EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText()); - EXPECT_TRUE(omnibox_view->IsSelectAll()); + EXPECT_FALSE(omnibox_view->IsSelectAll()); const AutocompleteResult& result = autocomplete_controller->result(); EXPECT_TRUE(result.empty()) << AutocompleteResultAsString(result); }
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc index f5f29cc..8b95017a 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/bind.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" @@ -31,6 +32,8 @@ #include "components/prefs/pref_service.h" #include "components/sync/driver/sync_service_utils.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/service_worker_context.h" +#include "content/public/browser/storage_partition.h" #include "extensions/features/features.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -38,9 +41,9 @@ #include "chrome/browser/autocomplete/keyword_extensions_delegate_impl.h" #endif -#if !defined(OS_ANDROID) namespace { +#if !defined(OS_ANDROID) // This list should be kept in sync with chrome/common/url_constants.h. // Only include useful sub-pages, confirmation alerts are not useful. const char* const kChromeSettingsSubPages[] = { @@ -58,9 +61,13 @@ chrome::kManageProfileSubPage, #endif }; +#endif // !defined(OS_ANDROID) + +// A callback that does nothing, called after the search service worker is +// started. +void NoopCallback(content::StartServiceWorkerForNavigationHintResult) {} } // namespace -#endif // !defined(OS_ANDROID) ChromeAutocompleteProviderClient::ChromeAutocompleteProviderClient( Profile* profile) @@ -284,6 +291,21 @@ image_service->Prefetch(url, traffic_annotation); } +void ChromeAutocompleteProviderClient::StartServiceWorker( + const GURL& destination_url) { + content::StoragePartition* partition = + content::BrowserContext::GetDefaultStoragePartition(profile_); + if (!partition) + return; + + content::ServiceWorkerContext* context = partition->GetServiceWorkerContext(); + if (!context) + return; + + context->StartServiceWorkerForNavigationHint(destination_url, + base::Bind(&NoopCallback)); +} + void ChromeAutocompleteProviderClient::OnAutocompleteControllerResultReady( AutocompleteController* controller) { content::NotificationService::current()->Notify(
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h index c5b284e0..6ac6792 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
@@ -53,6 +53,7 @@ history::KeywordID keyword_id, const base::string16& term) override; void PrefetchImage(const GURL& url) override; + void StartServiceWorker(const GURL& destination_url) override; void OnAutocompleteControllerResultReady( AutocompleteController* controller) override;
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc index 40d9dc85..eb09819 100644 --- a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc +++ b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
@@ -68,8 +68,9 @@ const FetchCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); - request_context_getter_->GetURLRequestContext()->cookie_store()-> - GetAllCookiesAsync(base::Bind(&OnFetchComplete, callback)); + request_context_getter_->GetURLRequestContext() + ->cookie_store() + ->GetAllCookiesAsync(base::BindOnce(&OnFetchComplete, callback)); } void BrowsingDataCookieHelper::DeleteCookieOnIOThread(
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc index dceb140..7230d80b 100644 --- a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc +++ b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc
@@ -71,9 +71,9 @@ PendingHosts* pending_hosts = new PendingHosts(); base::Closure completion = base::BarrierClosure( arraysize(types), - base::Bind(&BrowsingDataQuotaHelperImpl::OnGetOriginsComplete, - weak_factory_.GetWeakPtr(), callback, - base::Owned(pending_hosts))); + base::BindOnce(&BrowsingDataQuotaHelperImpl::OnGetOriginsComplete, + weak_factory_.GetWeakPtr(), callback, + base::Owned(pending_hosts))); for (const storage::StorageType& type : types) { quota_manager_->GetOriginsModifiedSince( @@ -105,9 +105,9 @@ QuotaInfoMap* quota_info = new QuotaInfoMap(); base::Closure completion = base::BarrierClosure( pending_hosts->size(), - base::Bind(&BrowsingDataQuotaHelperImpl::OnGetHostsUsageComplete, - weak_factory_.GetWeakPtr(), callback, - base::Owned(quota_info))); + base::BindOnce(&BrowsingDataQuotaHelperImpl::OnGetHostsUsageComplete, + weak_factory_.GetWeakPtr(), callback, + base::Owned(quota_info))); for (const auto& itr : *pending_hosts) { const std::string& host = itr.first;
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 6dc8dde..c1ffa1c3b 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -960,9 +960,10 @@ base::WaitableEvent* event = plugin_data_remover_->StartRemoving(delete_begin_); - base::WaitableEventWatcher::EventCallback watcher_callback = base::Bind( - &ChromeBrowsingDataRemoverDelegate::OnWaitableEventSignaled, - weak_ptr_factory_.GetWeakPtr()); + base::WaitableEventWatcher::EventCallback watcher_callback = + base::BindOnce( + &ChromeBrowsingDataRemoverDelegate::OnWaitableEventSignaled, + weak_ptr_factory_.GetWeakPtr()); watcher_.StartWatching(event, std::move(watcher_callback)); } else { // TODO(msramek): Store filters from the currently executed task on the @@ -1059,9 +1060,9 @@ clear_reporting_cache_.Start(); BrowserThread::PostTaskAndReply( BrowserThread::IO, FROM_HERE, - base::Bind(&ClearReportingCacheOnIOThread, - base::RetainedRef(std::move(context)), data_type_mask, - filter), + base::BindOnce(&ClearReportingCacheOnIOThread, + base::RetainedRef(std::move(context)), data_type_mask, + filter), UIThreadTrampoline(clear_reporting_cache_.GetCompletionCallback())); }
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 f19bb5e..05c1b04e 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
@@ -169,7 +169,7 @@ void FakeDBusCall(const chromeos::BoolDBusMethodCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(callback, chromeos::DBUS_METHOD_CALL_SUCCESS, true)); + base::BindOnce(callback, chromeos::DBUS_METHOD_CALL_SUCCESS, true)); } #endif @@ -185,8 +185,8 @@ get_cookie_success_ = false; cookie_store_->GetCookiesWithOptionsAsync( kOrigin1, net::CookieOptions(), - base::Bind(&RemoveCookieTester::GetCookieCallback, - base::Unretained(this))); + base::BindOnce(&RemoveCookieTester::GetCookieCallback, + base::Unretained(this))); message_loop_runner->Run(); return get_cookie_success_; } @@ -197,8 +197,8 @@ quit_closure_ = message_loop_runner->QuitClosure(); cookie_store_->SetCookieWithOptionsAsync( kOrigin1, "A=1", net::CookieOptions(), - base::Bind(&RemoveCookieTester::SetCookieCallback, - base::Unretained(this))); + base::BindOnce(&RemoveCookieTester::SetCookieCallback, + base::Unretained(this))); message_loop_runner->Run(); } @@ -253,7 +253,7 @@ net::URLRequestContext* request_context = sb_service->url_request_context()->GetURLRequestContext(); request_context->cookie_store()->DeleteAllAsync( - base::Bind(&RunClosureAfterCookiesCleared, run_loop.QuitClosure())); + base::BindOnce(&RunClosureAfterCookiesCleared, run_loop.QuitClosure())); run_loop.Run(); SetCookieStore(request_context->cookie_store());
diff --git a/chrome/browser/browsing_data/site_data_counting_helper.cc b/chrome/browser/browsing_data/site_data_counting_helper.cc index 9002e69..9cb47f8 100644 --- a/chrome/browser/browsing_data/site_data_counting_helper.cc +++ b/chrome/browser/browsing_data/site_data_counting_helper.cc
@@ -137,7 +137,7 @@ rq_context->GetURLRequestContext()->cookie_store(); if (cookie_store) { - cookie_store->GetAllCookiesAsync(base::Bind( + cookie_store->GetAllCookiesAsync(base::BindOnce( &SiteDataCountingHelper::GetCookiesCallback, base::Unretained(this))); } else { BrowserThread::PostTask(
diff --git a/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc b/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc index 6938e5f..2c322369 100644 --- a/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc +++ b/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc
@@ -122,8 +122,8 @@ url, "name", "A=1", url.host(), url.path(), time, base::Time(), time, true, false, net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT, - base::Bind(&SiteDataCountingHelperTest::DoneOnIOThread, - base::Unretained(this))); + base::BindOnce(&SiteDataCountingHelperTest::DoneOnIOThread, + base::Unretained(this))); } }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 537f13d..528d989 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -842,6 +842,13 @@ tab_helper->CreateChooserService(render_frame_host, std::move(request)); } +void CreateBudgetService(const service_manager::BindSourceInfo& source_info, + blink::mojom::BudgetServiceRequest request, + content::RenderFrameHost* render_frame_host) { + BudgetServiceImpl::Create(render_frame_host->GetProcess()->GetID(), + source_info, std::move(request)); +} + bool GetDataSaverEnabledPref(const PrefService* prefs) { // Enable data saver only when data saver pref is enabled and not part of // "Disabled" group of "SaveDataHeader" experiment. @@ -3373,6 +3380,9 @@ #elif defined(OS_LINUX) || defined(OS_WIN) frame_interfaces_->AddInterface(base::Bind(&ShareServiceImpl::Create)); #endif + + frame_interfaces_parameterized_->AddInterface( + base::Bind(&CreateBudgetService)); } #if BUILDFLAG(ENABLE_WEBRTC)
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index aeb4716..df2c387 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -7,6 +7,7 @@ "renderer": [ "autofill::mojom::AutofillDriver", "autofill::mojom::PasswordManagerDriver", + "blink::mojom::BudgetService", "chrome::mojom::CacheStatsRecorder", "chrome::mojom::NetBenchmarking", "extensions::StashService", @@ -51,6 +52,7 @@ "renderer": [ "autofill::mojom::AutofillDriver", "autofill::mojom::PasswordManagerDriver", + "blink::mojom::BudgetService", "blink::mojom::InstalledAppProvider", "blink::mojom::ShareService", "bluetooth::mojom::AdapterFactory",
diff --git a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc index 1234a84..3d5b2f0d 100644 --- a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc +++ b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
@@ -202,4 +202,26 @@ } } +using DistillablePageUtilsBrowserTestAllArticles = + DistillablePageUtilsBrowserTestOption<kAllArticles>; + +IN_PROC_BROWSER_TEST_F(DistillablePageUtilsBrowserTestAllArticles, + TestDelegate) { + const char* paths[] = {kSimpleArticlePath, kSimpleArticleIFramePath}; + for (unsigned i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) { + testing::InSequence dummy; + EXPECT_CALL(holder_, OnResult(true, false)).Times(1); + EXPECT_CALL(holder_, OnResult(true, true)) + .WillOnce(testing::InvokeWithoutArgs(QuitSoon)); + NavigateAndWait(paths[i], 0); + } + { + testing::InSequence dummy; + EXPECT_CALL(holder_, OnResult(false, false)).Times(1); + EXPECT_CALL(holder_, OnResult(false, true)) + .WillOnce(testing::InvokeWithoutArgs(QuitSoon)); + NavigateAndWait(kNonArticlePath, 0); + } +} + } // namespace dom_distiller
diff --git a/chrome/browser/feedback/system_logs/system_logs_fetcher.cc b/chrome/browser/feedback/system_logs/system_logs_fetcher.cc index fe9e2ba..2705636 100644 --- a/chrome/browser/feedback/system_logs/system_logs_fetcher.cc +++ b/chrome/browser/feedback/system_logs/system_logs_fetcher.cc
@@ -38,11 +38,6 @@ } // namespace -SystemLogsSource::SystemLogsSource(const std::string& source_name) - : source_name_(source_name) {} - -SystemLogsSource::~SystemLogsSource() {} - SystemLogsFetcher::SystemLogsFetcher(bool scrub_data) : response_(base::MakeUnique<SystemLogsResponse>()), num_pending_requests_(0),
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 0fb9012c..912f646ce 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -92,6 +92,14 @@ R"*("Learning" means that only the database construction is enabled, )*" R"*("Prefetching" that learning and prefetching are enabled.)*"; +const char kSpeculativeServiceWorkerStartOnQueryInputName[] = + "Enable speculative start of a service worker when a search is predicted."; + +const char kSpeculativeServiceWorkerStartOnQueryInputDescription[] = + "If enabled, when the user enters text in the omnibox that looks like a " + "a query, any service worker associated with the search engine the query " + "will be sent to is started early."; + const char kOffMainThreadFetchName[] = "Off-main-thread fetch for Web Workers"; const char kOffMainThreadFetchDescription[] = @@ -1939,11 +1947,13 @@ const char kReaderModeHeuristicsName[] = "Reader Mode triggering"; const char kReaderModeHeuristicsDescription[] = - "Determines what pages the Reader Mode button is shown on."; + "Determines what pages the Reader Mode infobar is shown on."; const char kReaderModeHeuristicsMarkup[] = "With article structured markup"; -const char kReaderModeHeuristicsAdaboost[] = "Appears to be an article"; +const char kReaderModeHeuristicsAdaboost[] = "Non-mobile-friendly articles"; + +const char kReaderModeHeuristicsAllArticles[] = "All articles"; const char kReaderModeHeuristicsAlwaysOff[] = "Never"; @@ -2397,14 +2407,6 @@ "allows to override the source used to retrieve these server-side " "suggestions."; -const char kEnableNtpRecentOfflineTabSuggestionsName[] = - "Show recent offline tabs on the New Tab page"; - -const char kEnableNtpRecentOfflineTabSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page will " - "contain pages that were captured offline during browsing (see " - "#offlining-recent-pages)"; - const char kEnableNtpAssetDownloadSuggestionsName[] = "Show asset downloads on the New Tab page"; @@ -2427,14 +2429,6 @@ "If enabled, the list of content suggestions on the New Tab page will " "contain recently visited bookmarks."; -const char kEnableNtpPhysicalWebPageSuggestionsName[] = - "Show Physical Web pages on the New Tab page"; - -const char kEnableNtpPhysicalWebPageSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page will " - "contain pages that are available through Physical Web (see " - "#enable-physical-web)"; - const char kEnableNtpForeignSessionsSuggestionsName[] = "Show recent foreign tabs on the New Tab page";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 916041f..b449e74 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -687,6 +687,9 @@ extern const char kSpeculativePrefetchName[]; extern const char kSpeculativePrefetchDescription[]; +extern const char kSpeculativeServiceWorkerStartOnQueryInputName[]; +extern const char kSpeculativeServiceWorkerStartOnQueryInputDescription[]; + extern const char kSpellingFeedbackFieldTrialName[]; extern const char kSpellingFeedbackFieldTrialDescription[]; @@ -1107,6 +1110,7 @@ extern const char kReaderModeHeuristicsDescription[]; extern const char kReaderModeHeuristicsMarkup[]; extern const char kReaderModeHeuristicsAdaboost[]; +extern const char kReaderModeHeuristicsAllArticles[]; extern const char kReaderModeHeuristicsAlwaysOff[]; extern const char kReaderModeHeuristicsAlwaysOn[];
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index e13fda3..23e8ba8 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -397,6 +397,8 @@ const GURL& url, const net::HostPortPair& host_port_pair, const content::GlobalRequestID& request_id, + int render_process_id, + int render_frame_id, ResourceType resource_type, bool is_download, bool was_cached, @@ -441,11 +443,15 @@ page_load_metrics::MetricsWebContentsObserver::FromWebContents( web_contents); if (metrics_observer) { + // Will be null for main or sub frame resources, when browser-side + // navigation is enabled. + content::RenderFrameHost* render_frame_host_or_null = + content::RenderFrameHost::FromID(render_process_id, render_frame_id); metrics_observer->OnRequestComplete( url, host_port_pair, frame_tree_node_id_getter.Run(), request_id, - resource_type, was_cached, std::move(data_reduction_proxy_data), - raw_body_bytes, original_content_length, request_creation_time, - net_error); + render_frame_host_or_null, resource_type, was_cached, + std::move(data_reduction_proxy_data), raw_body_bytes, + original_content_length, request_creation_time, net_error); } } } @@ -925,22 +931,23 @@ BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::BindOnce(&NotifyUIThreadOfRequestComplete, - info->GetWebContentsGetterForRequest(), - info->GetFrameTreeNodeIdGetterForRequest(), - url_request->url(), request_host_port, - info->GetGlobalRequestID(), info->GetResourceType(), - info->IsDownload(), url_request->was_cached(), - base::Passed(&data_reduction_proxy_data), net_error, - url_request->GetTotalReceivedBytes(), - url_request->GetRawBodyBytes(), original_content_length, - url_request->creation_time(), - base::TimeTicks::Now() - url_request->creation_time())); + base::BindOnce( + &NotifyUIThreadOfRequestComplete, + info->GetWebContentsGetterForRequest(), + info->GetFrameTreeNodeIdGetterForRequest(), url_request->url(), + request_host_port, info->GetGlobalRequestID(), info->GetChildID(), + info->GetRenderFrameID(), info->GetResourceType(), info->IsDownload(), + url_request->was_cached(), base::Passed(&data_reduction_proxy_data), + net_error, url_request->GetTotalReceivedBytes(), + url_request->GetRawBodyBytes(), original_content_length, + url_request->creation_time(), + base::TimeTicks::Now() - url_request->creation_time())); } content::PreviewsState ChromeResourceDispatcherHostDelegate::GetPreviewsState( const net::URLRequest& url_request, - content::ResourceContext* resource_context) { + content::ResourceContext* resource_context, + content::PreviewsState previews_to_allow) { ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context); data_reduction_proxy::DataReductionProxyIOData* data_reduction_proxy_io_data = io_data->data_reduction_proxy_io_data(); @@ -973,6 +980,15 @@ if (previews_state == content::PREVIEWS_UNSPECIFIED) return content::PREVIEWS_OFF; + + // If the allowed previews are limited, ensure we honor those limits. + if (previews_state != content::PREVIEWS_OFF && + previews_state != content::PREVIEWS_NO_TRANSFORM) { + previews_state = previews_state & previews_to_allow; + // If no valid previews are left, set the state explictly to PREVIEWS_OFF. + if (previews_state == 0) + previews_state = content::PREVIEWS_OFF; + } return previews_state; }
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h index 9511eee4..dfe215f 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h
@@ -87,7 +87,8 @@ // Returns a bitmask of potentially several Previews optimizations. content::PreviewsState GetPreviewsState( const net::URLRequest& url_request, - content::ResourceContext* resource_context) override; + content::ResourceContext* resource_context, + content::PreviewsState previews_to_allow) override; content::NavigationData* GetNavigationData( net::URLRequest* request) const override; std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
diff --git a/chrome/browser/media/BUILD.gn b/chrome/browser/media/BUILD.gn deleted file mode 100644 index 6f1a75b..0000000 --- a/chrome/browser/media/BUILD.gn +++ /dev/null
@@ -1,23 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# TODO(miu): Decentralize build configuration: Move source files and deps -# specific to chrome/browser/media sources from chrome/browser/BULID.gn and -# chrome/test/BUILD.gn into this BUILD.gn file. Also, remove the root BUILD.gn -# dependency on the cast_remoting_connector_fuzzer target after this is done. - -import("//testing/libfuzzer/fuzzer_test.gni") - -fuzzer_test("cast_remoting_connector_fuzzer") { - sources = [ - "cast_remoting_connector_fuzzertest.cc", - "cast_remoting_connector_messaging.cc", - "cast_remoting_connector_messaging.h", - ] - deps = [ - "//base", - ] - libfuzzer_options = [ "max_len = 128" ] - seed_corpus = "../../test/data/cast/cast_remoting_connector_fuzz_corpus" -}
diff --git a/chrome/browser/media/cast_remoting_connector.cc b/chrome/browser/media/cast_remoting_connector.cc index 16b3d5d..9d2388c 100644 --- a/chrome/browser/media/cast_remoting_connector.cc +++ b/chrome/browser/media/cast_remoting_connector.cc
@@ -10,14 +10,11 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" -#include "chrome/browser/media/cast_remoting_connector_messaging.h" #include "chrome/browser/media/cast_remoting_sender.h" #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_router_factory.h" -#include "chrome/browser/media/router/route_message_observer.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/common/chrome_features.h" -#include "chrome/common/media_router/media_source_helper.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -29,8 +26,6 @@ using media::mojom::RemotingStartFailReason; using media::mojom::RemotingStopReason; -using Messaging = CastRemotingConnectorMessaging; - class CastRemotingConnector::RemotingBridge : public media::mojom::Remoter { public: // Constructs a "bridge" to delegate calls between the given |source| and @@ -111,25 +106,6 @@ DISALLOW_COPY_AND_ASSIGN(RemotingBridge); }; -class CastRemotingConnector::MessageObserver - : public media_router::RouteMessageObserver { - public: - MessageObserver(media_router::MediaRouter* router, - const media_router::MediaRoute::Id& route_id, - CastRemotingConnector* connector) - : RouteMessageObserver(router, route_id), connector_(connector) {} - ~MessageObserver() final {} - - private: - void OnMessagesReceived( - const std::vector<content::PresentationConnectionMessage>& messages) - final { - connector_->ProcessMessagesFromRoute(messages); - } - - CastRemotingConnector* const connector_; -}; - // static const void* const CastRemotingConnector::kUserDataKey = &kUserDataKey; @@ -140,12 +116,15 @@ CastRemotingConnector* connector = static_cast<CastRemotingConnector*>(contents->GetUserData(kUserDataKey)); if (!connector) { + // TODO(xjz): Use TabAndroid::GetAndroidId() to get the tab ID when support + // remoting on Android. + const SessionID::id_type tab_id = SessionTabHelper::IdForTab(contents); + if (tab_id == -1) + return nullptr; connector = new CastRemotingConnector( media_router::MediaRouterFactory::GetApiForBrowserContext( contents->GetBrowserContext()), - media_router::MediaSourceForTabContentRemoting( - SessionTabHelper::IdForTab(contents)) - .id()); + tab_id); contents->SetUserData(kUserDataKey, base::WrapUnique(connector)); } return connector; @@ -160,8 +139,10 @@ auto* const contents = content::WebContents::FromRenderFrameHost(host); if (!contents) return; - CastRemotingConnector::Get(contents)->CreateBridge(std::move(source), - std::move(request)); + CastRemotingConnector* const connector = CastRemotingConnector::Get(contents); + if (!connector) + return; + connector->CreateBridge(std::move(source), std::move(request)); } namespace { @@ -175,15 +156,17 @@ } } // namespace -CastRemotingConnector::CastRemotingConnector( - media_router::MediaRouter* router, - const media_router::MediaSource::Id& media_source_id) - : media_router::MediaRoutesObserver(router), - media_source_id_(media_source_id), +CastRemotingConnector::CastRemotingConnector(media_router::MediaRouter* router, + int32_t tab_id) + : media_router_(router), + tab_id_(tab_id), enabled_features_(GetFeatureEnabledCapabilities()), - session_counter_(0), active_bridge_(nullptr), - weak_factory_(this) {} + binding_(this), + weak_factory_(this) { + VLOG(2) << "Register CastRemotingConnector for tab_id = " << tab_id_; + media_router_->RegisterRemotingSource(tab_id_, this); +} CastRemotingConnector::~CastRemotingConnector() { // Assume nothing about destruction/shutdown sequence of a tab. For example, @@ -195,6 +178,38 @@ notifyee->OnSinkGone(); notifyee->OnCastRemotingConnectorDestroyed(); } + media_router_->UnregisterRemotingSource(tab_id_); +} + +void CastRemotingConnector::ConnectToService( + media::mojom::MirrorServiceRemotingSourceRequest source_request, + media::mojom::MirrorServiceRemoterPtr remoter) { + DCHECK(!binding_.is_bound()); + DCHECK(!remoter_); + DCHECK(remoter); + DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__; + + binding_.Bind(std::move(source_request)); + binding_.set_connection_error_handler(base::Bind( + &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this))); + remoter_ = std::move(remoter); + remoter_.set_connection_error_handler(base::Bind( + &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this))); +} + +void CastRemotingConnector::OnMirrorServiceStopped() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__; + + if (binding_.is_bound()) + binding_.Close(); + remoter_.reset(); + + if (active_bridge_) + StopRemoting(active_bridge_, RemotingStopReason::SERVICE_GONE); + for (RemotingBridge* notifyee : bridges_) + notifyee->OnSinkGone(); } void CastRemotingConnector::CreateBridge(media::mojom::RemotingSourcePtr source, @@ -209,7 +224,8 @@ DCHECK(bridges_.find(bridge) == bridges_.end()); bridges_.insert(bridge); - if (message_observer_ && !active_bridge_) + // TODO(xjz): Pass the receiver's capabilities to the source. + if (remoter_ && !active_bridge_) bridge->OnSinkAvailable(enabled_features_); } @@ -226,14 +242,17 @@ void CastRemotingConnector::StartRemoting(RemotingBridge* bridge) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(bridges_.find(bridge) != bridges_.end()); + VLOG(2) << __func__; // Refuse to start if there is no remoting route available, or if remoting is // already active. - if (!message_observer_) { - bridge->OnStartFailed(RemotingStartFailReason::ROUTE_TERMINATED); + if (!remoter_) { + VLOG(2) << "Remoting start failed: No mirror service connected."; + bridge->OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED); return; } if (active_bridge_) { + VLOG(2) << "Remoting start failed: Cannot start multiple."; bridge->OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE); return; } @@ -249,12 +268,10 @@ } active_bridge_ = bridge; + remoter_->Start(); - // Send a start message to the Cast Provider. - ++session_counter_; // New remoting session ID. - SendMessageToProvider(base::StringPrintf( - Messaging::kStartRemotingMessageFormat, session_counter_)); - + // Assume the remoting session is always started successfully. If any failure + // occurs, OnError() will be called. bridge->OnStarted(); } @@ -265,10 +282,11 @@ media::mojom::RemotingDataStreamSenderRequest audio_sender_request, media::mojom::RemotingDataStreamSenderRequest video_sender_request) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__; // Refuse to start if there is no remoting route available, or if remoting is // not active for this |bridge|. - if (!message_observer_ || active_bridge_ != bridge) + if (!remoter_ || active_bridge_ != bridge) return; // Also, if neither audio nor video pipe was provided, or if a request for a // RemotingDataStreamSender was not provided for a data pipe, error-out early. @@ -279,39 +297,57 @@ return; } - // Hold on to the data pipe handles and interface requests until one/both - // CastRemotingSenders are created and ready for use. - pending_audio_pipe_ = std::move(audio_pipe); - pending_video_pipe_ = std::move(video_pipe); - pending_audio_sender_request_ = std::move(audio_sender_request); - pending_video_sender_request_ = std::move(video_sender_request); + const bool want_audio = audio_sender_request.is_pending(); + const bool want_video = video_sender_request.is_pending(); + remoter_->StartDataStreams( + want_audio, want_video, + base::BindOnce(&CastRemotingConnector::OnDataStreamsStarted, + weak_factory_.GetWeakPtr(), std::move(audio_pipe), + std::move(video_pipe), std::move(audio_sender_request), + std::move(video_sender_request))); +} - // Send a "start streams" message to the Cast Provider. The provider is - // responsible for creating and setting up a remoting Cast Streaming session - // that will result in new CastRemotingSender instances being created here in - // the browser process. - SendMessageToProvider(base::StringPrintf( - Messaging::kStartStreamsMessageFormat, session_counter_, - pending_audio_sender_request_.is_pending() ? 'Y' : 'N', - pending_video_sender_request_.is_pending() ? 'Y' : 'N')); +void CastRemotingConnector::OnDataStreamsStarted( + mojo::ScopedDataPipeConsumerHandle audio_pipe, + mojo::ScopedDataPipeConsumerHandle video_pipe, + media::mojom::RemotingDataStreamSenderRequest audio_sender_request, + media::mojom::RemotingDataStreamSenderRequest video_sender_request, + int32_t audio_stream_id, + int32_t video_stream_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(remoter_); + VLOG(2) << __func__ << ": audio_stream_id = " << audio_stream_id + << " video_stream_id = " << video_stream_id; + + if (!active_bridge_) { + remoter_->Stop(media::mojom::RemotingStopReason::SOURCE_GONE); + return; + } + + if (audio_sender_request.is_pending() && audio_stream_id > -1) { + cast::CastRemotingSender::FindAndBind( + audio_stream_id, std::move(audio_pipe), std::move(audio_sender_request), + base::Bind(&CastRemotingConnector::OnDataSendFailed, + weak_factory_.GetWeakPtr())); + } + if (video_sender_request.is_pending() && video_stream_id > -1) { + cast::CastRemotingSender::FindAndBind( + video_stream_id, std::move(video_pipe), std::move(video_sender_request), + base::Bind(&CastRemotingConnector::OnDataSendFailed, + weak_factory_.GetWeakPtr())); + } } void CastRemotingConnector::StopRemoting(RemotingBridge* bridge, RemotingStopReason reason) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__ << ": reason = " << reason; if (active_bridge_ != bridge) return; active_bridge_ = nullptr; - // Explicitly close the data pipes (and related requests) just in case the - // "start streams" operation was interrupted. - pending_audio_pipe_.reset(); - pending_video_pipe_.reset(); - pending_audio_sender_request_ = nullptr; - pending_video_sender_request_ = nullptr; - // Cancel all outstanding callbacks related to the remoting session. weak_factory_.InvalidateWeakPtrs(); @@ -320,181 +356,75 @@ bridge->OnSinkGone(); // Note: At this point, all sources should think the sink is gone. - SendMessageToProvider(base::StringPrintf( - Messaging::kStopRemotingMessageFormat, session_counter_)); - // Note: Once the Cast Provider sends back an acknowledgement message, all - // sources will be notified that the remoting sink is available again. + if (remoter_) + remoter_->Stop(reason); bridge->OnStopped(reason); } +void CastRemotingConnector::OnStopped(RemotingStopReason reason) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__ << ": reason = " << reason; + + if (!active_bridge_) + return; + StopRemoting(active_bridge_, reason); +} + void CastRemotingConnector::SendMessageToSink( RemotingBridge* bridge, const std::vector<uint8_t>& message) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // During an active remoting session, simply pass all binary messages through // to the sink. - if (!message_observer_ || active_bridge_ != bridge) + if (!remoter_ || active_bridge_ != bridge) return; - media_router::MediaRoutesObserver::router()->SendRouteBinaryMessage( - message_observer_->route_id(), - base::MakeUnique<std::vector<uint8_t>>(message), - base::Bind(&CastRemotingConnector::HandleSendMessageResult, - weak_factory_.GetWeakPtr())); + remoter_->SendMessageToSink(message); } -void CastRemotingConnector::SendMessageToProvider(const std::string& message) { +void CastRemotingConnector::OnMessageFromSink( + const std::vector<uint8_t>& message) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!message_observer_) + // During an active remoting session, simply pass all binary messages through + // to the source. + if (!active_bridge_) return; - - if (active_bridge_) { - media_router::MediaRoutesObserver::router()->SendRouteMessage( - message_observer_->route_id(), message, - base::Bind(&CastRemotingConnector::HandleSendMessageResult, - weak_factory_.GetWeakPtr())); - } else { - struct Helper { - static void IgnoreSendMessageResult(bool ignored) {} - }; - media_router::MediaRoutesObserver::router()->SendRouteMessage( - message_observer_->route_id(), message, - base::Bind(&Helper::IgnoreSendMessageResult)); - } + active_bridge_->OnMessageFromSink(message); } -void CastRemotingConnector::ProcessMessagesFromRoute( - const std::vector<content::PresentationConnectionMessage>& messages) { +void CastRemotingConnector::OnSinkAvailable( + media::mojom::SinkCapabilitiesPtr capabilities) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__; - // Note: If any calls to message parsing functions are added/changed here, - // please update cast_remoting_connector_fuzzertest.cc as well! - - for (const auto& message : messages) { - if (message.is_binary()) { - // All binary messages are passed through to the source during an active - // remoting session. - if (active_bridge_) - active_bridge_->OnMessageFromSink(*message.data); - - continue; - } - - // This is a notification message from the Cast Provider, about the - // execution state of the media remoting session between Chrome and the - // remote device. - - // If this is a "start streams" acknowledgement message, the - // CastRemotingSenders should now be available to begin consuming from - // the data pipes. - if (active_bridge_ && - Messaging::IsMessageForSession( - *message.message, Messaging::kStartedStreamsMessageFormatPartial, - session_counter_)) { - if (pending_audio_sender_request_.is_pending()) { - cast::CastRemotingSender::FindAndBind( - Messaging::GetStreamIdFromStartedMessage( - *message.message, - Messaging::kStartedStreamsMessageAudioIdSpecifier), - std::move(pending_audio_pipe_), - std::move(pending_audio_sender_request_), - base::Bind(&CastRemotingConnector::OnDataSendFailed, - weak_factory_.GetWeakPtr())); - } - if (pending_video_sender_request_.is_pending()) { - cast::CastRemotingSender::FindAndBind( - Messaging::GetStreamIdFromStartedMessage( - *message.message, - Messaging::kStartedStreamsMessageVideoIdSpecifier), - std::move(pending_video_pipe_), - std::move(pending_video_sender_request_), - base::Bind(&CastRemotingConnector::OnDataSendFailed, - weak_factory_.GetWeakPtr())); - } - } else if (active_bridge_ && - Messaging::IsMessageForSession(*message.message, - Messaging::kFailedMessageFormat, - session_counter_)) { - // If this is a failure message, call StopRemoting(). - StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE); - } else if (Messaging::IsMessageForSession(*message.message, - Messaging::kStoppedMessageFormat, - session_counter_)) { - // If this is a stop acknowledgement message, indicating that the last - // session was stopped, notify all sources that the sink is once again - // available. - if (active_bridge_) { - // Hmm...The Cast Provider was in a state that disagrees with this - // connector. Attempt to resolve this by shutting everything down to - // effectively reset to a known state. - LOG(WARNING) << "BUG: Cast Provider sent 'stopped' message during " - "an active remoting session."; - StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE); - } - for (RemotingBridge* notifyee : bridges_) - notifyee->OnSinkAvailable(enabled_features_); - } else { - LOG(WARNING) << "BUG: Unexpected message from Cast Provider: " - << *message.message; - } - } -} - -void CastRemotingConnector::HandleSendMessageResult(bool success) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - // A single message send failure is treated as fatal to an active remoting + // The receiver's capabilities should be unchanged during an active remoting // session. - if (!success && active_bridge_) - StopRemoting(active_bridge_, RemotingStopReason::MESSAGE_SEND_FAILED); + if (active_bridge_) { + LOG(WARNING) << "Unexpected OnSinkAvailable() call during an active" + << "remoting session."; + return; + } + + // TODO(xjz): Pass the receiver's capabilities to the sources. + for (RemotingBridge* notifyee : bridges_) + notifyee->OnSinkAvailable(enabled_features_); +} + +void CastRemotingConnector::OnError() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__; + + if (active_bridge_) + StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE); } void CastRemotingConnector::OnDataSendFailed() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + VLOG(2) << __func__; + // A single data send failure is treated as fatal to an active remoting // session. if (active_bridge_) StopRemoting(active_bridge_, RemotingStopReason::DATA_SEND_FAILED); } - -void CastRemotingConnector::OnRoutesUpdated( - const std::vector<media_router::MediaRoute>& routes, - const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // If a remoting route has already been identified, check that it still - // exists. Otherwise, shut down messaging and any active remoting, and notify - // the sources that remoting is no longer available. - if (message_observer_) { - for (const media_router::MediaRoute& route : routes) { - if (message_observer_->route_id() == route.media_route_id()) - return; // Remoting route still exists. Take no further action. - } - message_observer_.reset(); - if (active_bridge_) - StopRemoting(active_bridge_, RemotingStopReason::ROUTE_TERMINATED); - for (RemotingBridge* notifyee : bridges_) - notifyee->OnSinkGone(); - } - - // There shouldn't be an active RemotingBridge at this point, since there is - // currently no known remoting route. - DCHECK(!active_bridge_); - - // Scan |routes| for a new remoting route. If one is found, begin processing - // messages on the route, and notify the sources that remoting is now - // available. - for (const media_router::MediaRoute& route : routes) { - if (route.media_source().id() != media_source_id_) - continue; - message_observer_.reset(new MessageObserver( - media_router::MediaRoutesObserver::router(), route.media_route_id(), - this)); - // TODO(miu): In the future, scan the route ID for sink capabilities - // properties and pass these to the source in the OnSinkAvailable() - // notification. - for (RemotingBridge* notifyee : bridges_) - notifyee->OnSinkAvailable(enabled_features_); - break; - } -}
diff --git a/chrome/browser/media/cast_remoting_connector.h b/chrome/browser/media/cast_remoting_connector.h index d5bba5883..5156885 100644 --- a/chrome/browser/media/cast_remoting_connector.h +++ b/chrome/browser/media/cast_remoting_connector.h
@@ -9,13 +9,17 @@ #include "base/memory/weak_ptr.h" #include "base/supports_user_data.h" -#include "chrome/browser/media/router/media_routes_observer.h" +#include "media/mojo/interfaces/mirror_service_remoting.mojom.h" #include "media/mojo/interfaces/remoting.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" namespace content { class RenderFrameHost; class WebContents; -struct PresentationConnectionMessage; +} // namespace content + +namespace media_router { +class MediaRouter; } // CastRemotingConnector connects a single source (a media element in a render @@ -23,7 +27,12 @@ // instance of a CastRemotingConnector per source WebContents (representing a // collection of render frames), and it is created on-demand. The source in the // render process represents itself by providing a media::mojom::RemotingSource -// service instance. The sink is represented by the Media Router Cast Provider. +// service instance. The sink is represented by a MediaRemoter in the Cast Media +// Router Provider that handles the communication with the remote device. The +// CastRemotingConnector and the MediaRemoter can communicate with each other +// through the media::mojom::MirrorServiceRemoter and +// media::mojom::MirrorServiceRemotingSource interfaces when a sink that is +// capable of remoting is available. // // Whenever a candidate media source is created in a render frame, // ChromeContentBrowserClient will call CreateMediaRemoter() to instantiate a @@ -33,43 +42,41 @@ // notify when a sink becomes available for remoting, and to pass binary // messages from the sink back to the source. // -// At any time before or after the CastRemotingConnector is created, the -// Media Router Cast Provider may create a tab remoting media route. This -// indicates that the provider has found a sink that is capable of remoting and -// is available for use. At this point, CastRemotingConnector notifies all -// RemotingSources that a sink is available, and some time later a -// RemotingSource can request the start of a remoting session. Once the sink is -// no longer available, the provider terminates the route and -// CastRemotingConnector notifies all RemotingSources that the sink is gone. +// When the CastRemotingConnector is created, it registers itself in the +// media_router::MediaRouter with a tab ID that uniquely identifies it. When a +// mirroring route is created and available for remoting, the Cast MRP will +// create a MediaRemoter and notify MediaRouter, which notifies the +// CastRemotingConnector registered under the tab ID being remoted. At this +// point, the CastRemotingConnector can communicate with the MediaRemoter. When +// CastRemotingConnector gets notified that a sink is available, it notifies all +// RemotingSources, and some time later a RemotingSource can request the start +// of a remoting session. // // Note that only one RemotingSource can remote media at a time. Therefore, // CastRemotingConnector must mediate among simultaneous requests for media // remoting, and only allow one at a time. Currently, the policy is "first come, // first served." // -// When starting a remoting session, the CastRemotingConnector sends control -// messages to the Cast Provider. These control messages direct the provider to -// start/stop remoting with the remote device (e.g., launching apps or services -// on the remote device). Among its other duties, the provider will also set up -// a Cast Streaming session to provide a bitstream transport for the media. Once -// this is done, the provider sends notification messages back to -// CastRemotingConnector to acknowledge this. Then, CastRemotingConnector knows -// it can look-up and pass the mojo data pipe handles to CastRemotingSenders, -// and the remoting session will be fully active. The CastRemotingConnector is -// responsible for passing small binary messages between the source and sink, -// while the CastRemotingSender handles the high-volume media data transfer. +// When starting a remoting session, the Cast MRP will also set up a Cast +// Streaming session to provide a bitstream transport for the media. Once this +// is done, the MediaRemoter notifies the CastRemotingConnector. Then, +// CastRemotingConnector knows it can look-up and pass the mojo data pipe +// handles to CastRemotingSenders, and the remoting session will be fully active +// The CastRemotingConnector is responsible for passing small binary messages +// between the source and sink, while the CastRemotingSender handles the +// high-volume media data transfer. // // Please see the unit tests in cast_remoting_connector_unittest.cc as a -// reference for how CastRemotingConnector and a Cast Provider interact to +// reference for how CastRemotingConnector and a MediaRemoter interact to // start/execute/stop remoting sessions. -class CastRemotingConnector - : public base::SupportsUserData::Data, - public media_router::MediaRoutesObserver { +class CastRemotingConnector : public base::SupportsUserData::Data, + public media::mojom::MirrorServiceRemotingSource { public: ~CastRemotingConnector() final; // Returns the instance of the CastRemotingConnector associated with - // |source_contents|, creating a new instance if needed. + // |source_contents|, creating a new instance if needed. Returns nullptr if + // |source_contents| doesn't have a valid tab ID. static CastRemotingConnector* Get(content::WebContents* source_contents); // Used by ChromeContentBrowserClient to request a binding to a new @@ -78,6 +85,13 @@ media::mojom::RemotingSourcePtr source, media::mojom::RemoterRequest request); + // Called when a MediaRemoter is created and started in the Cast MRP. This + // call connects the CastRemotingConnector with the MediaRemoter. Remoting + // sessions can only be started after this is called. + void ConnectToService( + media::mojom::MirrorServiceRemotingSourceRequest source_request, + media::mojom::MirrorServiceRemoterPtr remoter); + private: // Allow unit tests access to the private constructor and CreateBridge() // method, since unit tests don't have a complete browser (i.e., with a @@ -91,15 +105,9 @@ // mojo message pipe. class RemotingBridge; - // A RouteMessageObserver for the remoting route that passes messages from the - // Cast Provider back to this connector. An instance of this class only exists - // while a remoting route is available, and is owned by CastRemotingConnector. - class MessageObserver; - - // Main constructor. |media_source_id| refers to any remoted content managed + // Main constructor. |tab_id| refers to any remoted content managed // by this instance (i.e., any remoted content from one tab/WebContents). - CastRemotingConnector(media_router::MediaRouter* router, - const media_router::MediaSource::Id& media_source_id); + CastRemotingConnector(media_router::MediaRouter* router, int32_t tab_id); // Creates a RemotingBridge that implements the requested Remoter service, and // binds it to the interface |request|. @@ -113,6 +121,12 @@ void DeregisterBridge(RemotingBridge* bridge, media::mojom::RemotingStopReason reason); + // media::mojom::MirrorServiceRemotingSource implementations. + void OnSinkAvailable(media::mojom::SinkCapabilitiesPtr capabilities) override; + void OnMessageFromSink(const std::vector<uint8_t>& message) override; + void OnStopped(media::mojom::RemotingStopReason reason) override; + void OnError() override; + // These methods are called by RemotingBridge to forward media::mojom::Remoter // calls from a source through to this connector. They ensure that only one // source is allowed to be in a remoting session at a time, and that no source @@ -129,35 +143,25 @@ void SendMessageToSink(RemotingBridge* bridge, const std::vector<uint8_t>& message); - // Send a control message to the Cast Provider. This may or may not succeed, - // with the success status reported later via HandleSendMessageResult(). - void SendMessageToProvider(const std::string& message); + // Called when RTP streams are started. + void OnDataStreamsStarted( + mojo::ScopedDataPipeConsumerHandle audio_pipe, + mojo::ScopedDataPipeConsumerHandle video_pipe, + media::mojom::RemotingDataStreamSenderRequest audio_sender_request, + media::mojom::RemotingDataStreamSenderRequest video_sender_request, + int32_t audio_stream_id, + int32_t video_stream_id); - // Called by the current MessageObserver to process messages observed on the - // remoting route. There are two types of messages: 1) text notification - // messages from the Cast Provider, to report on the current state of a - // remoting session between Chrome and the remote device, and 2) binary - // messages, to be passed directly to the active remoting source during a - // remoting session. - void ProcessMessagesFromRoute( - const std::vector<content::PresentationConnectionMessage>& messages); - - // Error handlers for message/data sending during an active remoting - // session. When a failure occurs, these immediately force-stop remoting. - void HandleSendMessageResult(bool success); + // Error handlers for message sending during an active remoting session. When + // a failure occurs, these immediately force-stop remoting. void OnDataSendFailed(); - // MediaRoutesObserver implementation: Scans |routes| to check whether the - // existing remoting route has gone away and/or there is a new remoting route - // established, and take the necessary actions to notify sources and/or - // shutdown an active remoting session. - void OnRoutesUpdated( - const std::vector<media_router::MediaRoute>& routes, - const std::vector<media_router::MediaRoute::Id>& ignored) final; + // Called when any connection error/lost occurs with the MediaRemoter. + void OnMirrorServiceStopped(); - // The MediaSource ID referring to any remoted content managed by this - // CastRemotingConnector. - const media_router::MediaSource::Id media_source_id_; + media_router::MediaRouter* const media_router_; + + const int32_t tab_id_; // Describes the sink's capabilities according to what has been enabled via // |features::kMediaRemoting|. These are controlled manually via @@ -169,28 +173,12 @@ // set. std::set<RemotingBridge*> bridges_; - // Created when the Media Router Cast Provider has created a media remoting - // route to a sink that supports remoting and is available for use. This - // observer simply dispatches messages from the Cast Provider and sink back to - // this connector. Once the route is gone, this is reset to null. - std::unique_ptr<MessageObserver> message_observer_; - - // Incremented each time StartRemoting() is called, and used as a "current - // session ID" to ensure that control messaging between this connector and the - // Cast Provider are referring to the same remoting session. This allows both - // this connector and the provider to ignore stale messages. - unsigned int session_counter_; - // When non-null, an active remoting session is taking place, with this // pointing to the RemotingBridge being used to communicate with the source. RemotingBridge* active_bridge_; - // These temporarily hold the mojo data pipe handles and interface requests - // until hand-off to the CastRemotingSenders. - mojo::ScopedDataPipeConsumerHandle pending_audio_pipe_; - mojo::ScopedDataPipeConsumerHandle pending_video_pipe_; - media::mojom::RemotingDataStreamSenderRequest pending_audio_sender_request_; - media::mojom::RemotingDataStreamSenderRequest pending_video_sender_request_; + mojo::Binding<media::mojom::MirrorServiceRemotingSource> binding_; + media::mojom::MirrorServiceRemoterPtr remoter_; // Produces weak pointers that are only valid for the current remoting // session. This is used to cancel any outstanding callbacks when a remoting
diff --git a/chrome/browser/media/cast_remoting_connector_messaging.cc b/chrome/browser/media/cast_remoting_connector_messaging.cc deleted file mode 100644 index d55d6a5..0000000 --- a/chrome/browser/media/cast_remoting_connector_messaging.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/media/cast_remoting_connector_messaging.h" - -#include <stdio.h> - -#include <limits> - -#include "base/strings/string_number_conversions.h" - -const char CastRemotingConnectorMessaging::kMessageFieldSeparator = ':'; -const char CastRemotingConnectorMessaging::kStartRemotingMessageFormat[] = - "START_CAST_REMOTING:session=%x"; -const char CastRemotingConnectorMessaging::kStartStreamsMessageFormat[] = - "START_CAST_REMOTING_STREAMS:session=%x:audio=%c:video=%c"; -const char -CastRemotingConnectorMessaging::kStartedStreamsMessageFormatPartial[] = - "STARTED_CAST_REMOTING_STREAMS:session=%x"; -const char -CastRemotingConnectorMessaging::kStartedStreamsMessageAudioIdSpecifier[] = - ":audio_stream_id="; -const char -CastRemotingConnectorMessaging::kStartedStreamsMessageVideoIdSpecifier[] = - ":video_stream_id="; -const char CastRemotingConnectorMessaging::kStopRemotingMessageFormat[] = - "STOP_CAST_REMOTING:session=%x"; -const char CastRemotingConnectorMessaging::kStoppedMessageFormat[] = - "STOPPED_CAST_REMOTING:session=%x"; -const char CastRemotingConnectorMessaging::kFailedMessageFormat[] = - "FAILED_CAST_REMOTING:session=%x"; - -// static -bool CastRemotingConnectorMessaging::IsMessageForSession( - const std::string& message, const char* format, - unsigned int expected_session_id) { - unsigned int session_id; - if (sscanf(message.c_str(), format, &session_id) == 1) - return session_id == expected_session_id; - return false; -} - -// static -int32_t CastRemotingConnectorMessaging::GetStreamIdFromStartedMessage( - base::StringPiece message, base::StringPiece specifier) { - auto start = message.find(specifier); - if (start == std::string::npos) - return -1; - start += specifier.size(); - if (start + 1 >= message.size()) - return -1; // Must be at least one hex digit following the specifier. - const auto length = message.find(kMessageFieldSeparator, start) - start; - int parsed_value; - if (!base::HexStringToInt(message.substr(start, length), &parsed_value) || - parsed_value < 0 || - parsed_value > std::numeric_limits<int32_t>::max()) { - return -1; // Non-hex digits, or outside valid range. - } - return static_cast<int32_t>(parsed_value); -}
diff --git a/chrome/browser/media/cast_remoting_connector_messaging.h b/chrome/browser/media/cast_remoting_connector_messaging.h deleted file mode 100644 index dbe6ae6..0000000 --- a/chrome/browser/media/cast_remoting_connector_messaging.h +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_MESSAGING_H_ -#define CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_MESSAGING_H_ - -#include <stdint.h> - -#include <string> - -#include "base/strings/string_piece.h" - -// Utility functions for parsing messages from the Cast Provider to -// CastRemotingConnector. These have been broken-out into this separate module -// to allow for efficient building, linking and execution of these routines for -// fuzzer testing. -// -// Note: If any additions/changes are made here, please update -// cast_remoting_connector_fuzzertest.cc as well! -class CastRemotingConnectorMessaging { - public: - // Returns true if the given |message| from the Cast Provider matches the - // given |format| and the session ID in the |message| is equal to the - // |expected_session_id|. - static bool IsMessageForSession(const std::string& message, - const char* format, - unsigned int expected_session_id); - - // Scans |message| for |specifier| and extracts the remoting stream ID that - // follows the specifier. Returns a negative value on error. - static int32_t GetStreamIdFromStartedMessage(base::StringPiece message, - base::StringPiece specifier); - - // Simple command messages sent from/to the CastRemotingConnector to/from the - // Media Router Cast Provider to start/stop media remoting to a Cast device. - // - // Field separator (for tokenizing parts of messages). - static const char kMessageFieldSeparator; - // Message sent by CastRemotingConnector to Cast provider to start remoting. - // Example: - // "START_CAST_REMOTING:session=1f" - static const char kStartRemotingMessageFormat[]; - // Message sent by CastRemotingConnector to Cast provider to start the - // remoting RTP stream(s). Example: - // "START_CAST_REMOTING_STREAMS:session=1f:audio=N:video=Y" - static const char kStartStreamsMessageFormat[]; - // Start acknowledgement message sent by Cast provider to - // CastRemotingConnector once remoting RTP streams have been set up. Examples: - // "STARTED_CAST_REMOTING_STREAMS:session=1f:audio_stream_id=2e:" - // "video_stream_id=3d" - // "STARTED_CAST_REMOTING_STREAMS:session=1f:video_stream_id=b33f" - static const char kStartedStreamsMessageFormatPartial[]; - static const char kStartedStreamsMessageAudioIdSpecifier[]; - static const char kStartedStreamsMessageVideoIdSpecifier[]; - // Stop message sent by CastRemotingConnector to Cast provider. Example: - // "STOP_CAST_REMOTING:session=1f" - static const char kStopRemotingMessageFormat[]; - // Stop acknowledgement message sent by Cast provider to CastRemotingConnector - // once remoting is available again after the last session ended. Example: - // "STOPPED_CAST_REMOTING:session=1f" - static const char kStoppedMessageFormat[]; - // Failure message sent by Cast provider to CastRemotingConnector any time - // there was a fatal error (e.g., the Cast provider failed to set up the RTP - // streams, or there was some unexpected external event). Example: - // "FAILED_CAST_REMOTING:session=1f" - static const char kFailedMessageFormat[]; -}; - -#endif // CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_MESSAGING_H_
diff --git a/chrome/browser/media/cast_remoting_connector_unittest.cc b/chrome/browser/media/cast_remoting_connector_unittest.cc index 17467c88..2a6b6385 100644 --- a/chrome/browser/media/cast_remoting_connector_unittest.cc +++ b/chrome/browser/media/cast_remoting_connector_unittest.cc
@@ -8,24 +8,21 @@ #include <vector> #include "base/callback.h" +#include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" -#include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/browser/media/router/mock_media_router.h" -#include "chrome/browser/media/router/route_message_observer.h" -#include "chrome/browser/media/router/test_helper.h" #include "chrome/common/media_router/media_route.h" #include "chrome/common/media_router/media_source.h" #include "content/public/browser/browser_thread.h" -#include "content/public/common/presentation_connection_message.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "media/mojo/interfaces/mirror_service_remoting.mojom.h" #include "media/mojo/interfaces/remoting.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using content::BrowserThread; -using content::PresentationConnectionMessage; using media::mojom::RemoterPtr; using media::mojom::RemoterRequest; @@ -34,28 +31,17 @@ using media::mojom::RemotingSourceRequest; using media::mojom::RemotingStartFailReason; using media::mojom::RemotingStopReason; - -using media_router::MediaRoutesObserver; -using media_router::MediaRoute; -using media_router::MediaSource; -using media_router::PresentationConnectionMessageToString; -using media_router::RouteMessageObserver; +using media::mojom::MirrorServiceRemoterPtr; +using media::mojom::MirrorServiceRemoterRequest; +using media::mojom::MirrorServiceRemotingSourcePtr; +using media::mojom::MirrorServiceRemotingSourceRequest; using ::testing::_; using ::testing::AtLeast; namespace { -constexpr char kRemotingMediaSource[] = - "urn:x-org.chromium.media:source:tab_content_remoting:123"; -constexpr char kRemotingMediaSink[] = "wiggles"; -constexpr char kRemotingMediaRoute[] = - "urn:x-org.chromium:media:route:garbly_gook_ssi7m4oa8oma7rasd/cast-wiggles"; - -constexpr char kTabMirroringMediaSource[] = - "urn:x-org.chromium.media:source:tab:123"; -constexpr char kTabMirroringMediaRoute[] = - "urn:x-org.chromium:media:route:bloopity_blop_ohun48i56nh9oid/cast-wiggles"; +constexpr int32_t kRemotingTabId = 2; constexpr RemotingSinkCapabilities kAllCapabilities = RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING; @@ -65,146 +51,40 @@ // if any methods were called that should not have been called. class FakeMediaRouter : public media_router::MockMediaRouter { public: - FakeMediaRouter() - : routes_observer_(nullptr), message_observer_(nullptr), - weak_factory_(this) {} + FakeMediaRouter() : weak_factory_(this) {} ~FakeMediaRouter() final {} - // - // These methods are called by test code to create/destroy a media route and - // pass messages in both directions. - // - - void OnRemotingRouteExists(bool exists) { - routes_.clear(); - - // Always add a non-remoting route to make sure CastRemotingConnector - // ignores non-remoting routes. - routes_.push_back(MediaRoute( - kTabMirroringMediaRoute, MediaSource(kTabMirroringMediaSource), - kRemotingMediaSink, "Cast Tab Mirroring", false, "", false)); - - if (exists) { - routes_.push_back(MediaRoute( - kRemotingMediaRoute, MediaSource(kRemotingMediaSource), - kRemotingMediaSink, "Cast Media Remoting", false, "", false)); - } else { - // Cancel delivery of all messages in both directions. - inbound_messages_.clear(); - for (auto& entry : outbound_messages_) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(std::move(entry.second), false)); - } - outbound_messages_.clear(); - } - - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(&FakeMediaRouter::DoUpdateRoutes, - weak_factory_.GetWeakPtr())); + void RegisterRemotingSource(int32_t tab_id, + CastRemotingConnector* remoting_source) final { + EXPECT_EQ(-1, tab_id_); + tab_id_ = tab_id; + connector_ = remoting_source; } - void OnMessageFromProvider(const std::string& message) { - inbound_messages_.emplace_back(message); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&FakeMediaRouter::DoDeliverInboundMessages, - weak_factory_.GetWeakPtr())); + void UnregisterRemotingSource(int32_t tab_id) final { + EXPECT_EQ(tab_id, tab_id_); + tab_id_ = -1; + connector_ = nullptr; } - void OnBinaryMessageFromProvider(const std::vector<uint8_t>& message) { - inbound_messages_.emplace_back(message); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&FakeMediaRouter::DoDeliverInboundMessages, - weak_factory_.GetWeakPtr())); + void OnMediaRemoterCreated( + int32_t tab_id, + MirrorServiceRemoterPtr remoter, + MirrorServiceRemotingSourceRequest remoting_source) { + if (tab_id != tab_id_) + return; + + EXPECT_TRUE(connector_); + connector_->ConnectToService(std::move(remoting_source), + std::move(remoter)); } - void TakeMessagesSentToProvider( - bool text, - std::vector<PresentationConnectionMessage>* messages) { - decltype(outbound_messages_) untaken_messages; - for (auto& entry : outbound_messages_) { - if (!entry.first.is_binary() == text) { - messages->push_back(entry.first); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(std::move(entry.second), true)); - } else { - untaken_messages.push_back(std::move(entry)); - } - } - outbound_messages_.swap(untaken_messages); - } - - protected: - void RegisterMediaRoutesObserver(MediaRoutesObserver* observer) final { - CHECK(!routes_observer_); - routes_observer_ = observer; - CHECK(routes_observer_); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(&FakeMediaRouter::DoUpdateRoutes, - weak_factory_.GetWeakPtr())); - } - - void UnregisterMediaRoutesObserver(MediaRoutesObserver* observer) final { - CHECK_EQ(routes_observer_, observer); - routes_observer_ = nullptr; - } - - void RegisterRouteMessageObserver(RouteMessageObserver* observer) final { - CHECK(!message_observer_); - message_observer_ = observer; - CHECK(message_observer_); - } - - void UnregisterRouteMessageObserver(RouteMessageObserver* observer) final { - CHECK_EQ(message_observer_, observer); - message_observer_ = nullptr; - } - - void SendRouteMessage(const MediaRoute::Id& route_id, - const std::string& text, - SendRouteMessageCallback callback) final { - EXPECT_EQ(message_observer_->route_id(), route_id); - ASSERT_FALSE(callback.is_null()); - PresentationConnectionMessage message(text); - outbound_messages_.emplace_back(std::move(message), std::move(callback)); - } - - void SendRouteBinaryMessage(const MediaRoute::Id& route_id, - std::unique_ptr<std::vector<uint8_t>> data, - SendRouteMessageCallback callback) final { - EXPECT_EQ(message_observer_->route_id(), route_id); - ASSERT_TRUE(!!data); - ASSERT_FALSE(callback.is_null()); - PresentationConnectionMessage message(std::move(*data)); - outbound_messages_.emplace_back(std::move(message), std::move(callback)); - } + // Get the registered tab ID. + int32_t tab_id() const { return tab_id_; } private: - // Asynchronous callback to notify the MediaRoutesObserver of a change in - // routes. - void DoUpdateRoutes() { - if (routes_observer_) - routes_observer_->OnRoutesUpdated(routes_, std::vector<MediaRoute::Id>()); - } - - // Asynchronous callback to deliver messages to the RouteMessageObserver. - void DoDeliverInboundMessages() { - if (message_observer_) - message_observer_->OnMessagesReceived(inbound_messages_); - inbound_messages_.clear(); - } - - MediaRoutesObserver* routes_observer_; - RouteMessageObserver* message_observer_; - - std::vector<MediaRoute> routes_; - // Messages from Cast Provider to the connector. - std::vector<PresentationConnectionMessage> inbound_messages_; - // Messages from the connector to the Cast Provider. - using OutboundMessageAndCallback = - std::pair<PresentationConnectionMessage, SendRouteMessageCallback>; - std::vector<OutboundMessageAndCallback> outbound_messages_; + int32_t tab_id_ = -1; + CastRemotingConnector* connector_ = nullptr; base::WeakPtrFactory<FakeMediaRouter> weak_factory_; }; @@ -229,15 +109,53 @@ mojo::Binding<media::mojom::RemotingSource> binding_; }; +class MockMediaRemoter : public media::mojom::MirrorServiceRemoter { + public: + explicit MockMediaRemoter(FakeMediaRouter* media_router) : binding_(this) { + MirrorServiceRemoterPtr remoter; + binding_.Bind(mojo::MakeRequest(&remoter)); + media_router->OnMediaRemoterCreated(kRemotingTabId, std::move(remoter), + mojo::MakeRequest(&source_)); + } + ~MockMediaRemoter() final {} + + void OnSinkAvailable() { + media::mojom::SinkCapabilitiesPtr capabilities = + media::mojom::SinkCapabilities::New(); + source_->OnSinkAvailable(std::move(capabilities)); + } + + void SendMessageToSource(const std::vector<uint8_t>& message) { + source_->OnMessageFromSink(message); + } + + void OnStopped(RemotingStopReason reason) { source_->OnStopped(reason); } + + void OnError() { source_->OnError(); } + + // media::mojom::MirrorServiceRemoter implementations. + void StartDataStreams(bool audio, + bool video, + StartDataStreamsCallback callback) override {} + MOCK_METHOD0(Start, void()); + MOCK_METHOD1(Stop, void(RemotingStopReason)); + MOCK_METHOD1(SendMessageToSink, void(const std::vector<uint8_t>&)); + + private: + mojo::Binding<media::mojom::MirrorServiceRemoter> binding_; + MirrorServiceRemotingSourcePtr source_; +}; + } // namespace class CastRemotingConnectorTest : public ::testing::Test { public: - CastRemotingConnectorTest() - : connector_(&media_router_, kRemotingMediaSource) { + CastRemotingConnectorTest() : connector_(&media_router_, kRemotingTabId) { // HACK: Override feature flags for testing. const_cast<RemotingSinkCapabilities&>(connector_.enabled_features_) = kAllCapabilities; + + EXPECT_EQ(kRemotingTabId, media_router_.tab_id()); } void TearDown() final { @@ -257,77 +175,14 @@ return remoter_ptr; } - void ProviderDiscoversSink() { - media_router_.OnRemotingRouteExists(true); - } - - void ProviderLosesSink() { - media_router_.OnRemotingRouteExists(false); - } - - void ConnectorSentMessageToProvider(const std::string& expected_message) { - std::vector<PresentationConnectionMessage> messages; - media_router_.TakeMessagesSentToProvider(true, &messages); - bool did_see_expected_message = false; - for (const auto& message : messages) { - if (expected_message == message.message) { - did_see_expected_message = true; - } else { - ADD_FAILURE() << "Unexpected message: " - << PresentationConnectionMessageToString(message); - } - } - EXPECT_TRUE(did_see_expected_message); - } - - void ConnectorSentMessageToSink( - const std::vector<uint8_t>& expected_message) { - std::vector<PresentationConnectionMessage> messages; - media_router_.TakeMessagesSentToProvider(false, &messages); - bool did_see_expected_message = false; - for (const auto& message : messages) { - if (expected_message == message.data) { - did_see_expected_message = true; - } else { - ADD_FAILURE() << "Unexpected message: " - << PresentationConnectionMessageToString(message); - } - } - EXPECT_TRUE(did_see_expected_message); - } - - void ConnectorSentNoMessagesToProvider() { - std::vector<PresentationConnectionMessage> messages; - media_router_.TakeMessagesSentToProvider(true, &messages); - EXPECT_TRUE(messages.empty()); - } - - void ConnectorSentNoMessagesToSink() { - std::vector<PresentationConnectionMessage> messages; - media_router_.TakeMessagesSentToProvider(false, &messages); - EXPECT_TRUE(messages.empty()); - } - - void ProviderPassesMessageFromSink( - const std::vector<uint8_t>& message) { - media_router_.OnBinaryMessageFromProvider(message); - } - - void ProviderSaysToRemotingConnector(const std::string& message) { - media_router_.OnMessageFromProvider(message); - } - - void MediaRouterTerminatesRoute() { - media_router_.OnRemotingRouteExists(false); - } - static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } + FakeMediaRouter media_router_; + private: content::TestBrowserThreadBundle browser_thread_bundle_; - FakeMediaRouter media_router_; CastRemotingConnector connector_; }; @@ -344,12 +199,15 @@ MockRemotingSource source; RemoterPtr remoter = CreateRemoter(&source); + std::unique_ptr<MockMediaRemoter> media_remoter = + base::MakeUnique<MockMediaRemoter>(&media_router_); + EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); - ProviderDiscoversSink(); + media_remoter->OnSinkAvailable(); RunUntilIdle(); EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1)); - ProviderLosesSink(); + media_remoter.reset(); RunUntilIdle(); } @@ -360,14 +218,17 @@ MockRemotingSource source2; RemoterPtr remoter2 = CreateRemoter(&source2); + std::unique_ptr<MockMediaRemoter> media_remoter = + base::MakeUnique<MockMediaRemoter>(&media_router_); + EXPECT_CALL(source1, OnSinkAvailable(kAllCapabilities)).Times(1); EXPECT_CALL(source2, OnSinkAvailable(kAllCapabilities)).Times(1); - ProviderDiscoversSink(); + media_remoter->OnSinkAvailable(); RunUntilIdle(); EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); - ProviderLosesSink(); + media_remoter.reset(); RunUntilIdle(); } @@ -375,8 +236,11 @@ std::unique_ptr<MockRemotingSource> source(new MockRemotingSource); RemoterPtr remoter = CreateRemoter(source.get()); + std::unique_ptr<MockMediaRemoter> media_remoter = + base::MakeUnique<MockMediaRemoter>(&media_router_); + EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1); - ProviderDiscoversSink(); + media_remoter->OnSinkAvailable(); RunUntilIdle(); source.reset(); @@ -387,14 +251,28 @@ MockRemotingSource source; RemoterPtr remoter = CreateRemoter(&source); + std::unique_ptr<MockMediaRemoter> media_remoter = + base::MakeUnique<MockMediaRemoter>(&media_router_); + EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); - ProviderDiscoversSink(); + media_remoter->OnSinkAvailable(); RunUntilIdle(); remoter.reset(); RunUntilIdle(); } +TEST_F(CastRemotingConnectorTest, NoConnectedMediaRemoter) { + MockRemotingSource source; + RemoterPtr remoter = CreateRemoter(&source); + + EXPECT_CALL(source, + OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED)) + .Times(1); + remoter->Start(); + RunUntilIdle(); +} + namespace { // The possible ways a remoting session may be terminated in the "full @@ -424,6 +302,8 @@ RemoterPtr remoter = CreateRemoter(source.get()); std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); RemoterPtr other_remoter = CreateRemoter(other_source.get()); + std::unique_ptr<MockMediaRemoter> media_remoter = + base::MakeUnique<MockMediaRemoter>(&media_router_); // Throughout this test |other_source| should not participate in the // remoting session, and so these method calls should never occur: @@ -437,7 +317,7 @@ .RetiresOnSaturation(); EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) .RetiresOnSaturation(); - ProviderDiscoversSink(); + media_remoter->OnSinkAvailable(); RunUntilIdle(); // When |source| starts a remoting session, |other_source| is notified the @@ -445,24 +325,28 @@ // and |source| is notified that its request was successful. EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*media_remoter, Start()).Times(1).RetiresOnSaturation(); remoter->Start(); RunUntilIdle(); - ConnectorSentMessageToProvider("START_CAST_REMOTING:session=1"); // The |source| should now be able to send binary messages to the sink. // |other_source| should not! const std::vector<uint8_t> message_to_sink = { 3, 1, 4, 1, 5, 9 }; + EXPECT_CALL(*media_remoter, SendMessageToSink(message_to_sink)) + .Times(1) + .RetiresOnSaturation(); remoter->SendMessageToSink(message_to_sink); const std::vector<uint8_t> ignored_message_to_sink = { 1, 2, 3 }; + EXPECT_CALL(*media_remoter, SendMessageToSink(ignored_message_to_sink)) + .Times(0); other_remoter->SendMessageToSink(ignored_message_to_sink); RunUntilIdle(); - ConnectorSentMessageToSink(message_to_sink); // The sink should also be able to send binary messages to the |source|. const std::vector<uint8_t> message_to_source = { 2, 7, 1, 8, 2, 8 }; EXPECT_CALL(*source, OnMessageFromSink(message_to_source)).Times(1) .RetiresOnSaturation(); - ProviderPassesMessageFromSink(message_to_source); + media_remoter->SendMessageToSource(message_to_source); RunUntilIdle(); // The |other_source| should not be allowed to start a remoting session. @@ -471,7 +355,6 @@ .Times(1).RetiresOnSaturation(); other_remoter->Start(); RunUntilIdle(); - ConnectorSentNoMessagesToProvider(); // What happens from here depends on how this remoting session will end... switch (how_it_ends()) { @@ -482,19 +365,19 @@ const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK; EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*media_remoter, Stop(reason)).Times(1).RetiresOnSaturation(); remoter->Stop(reason); RunUntilIdle(); - ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1"); // Since remoting is stopped, any further messaging in either direction // must be dropped. const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); + EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); remoter->SendMessageToSink(message_to_sink); - ProviderPassesMessageFromSink(message_to_source); + media_remoter->SendMessageToSource(message_to_source); RunUntilIdle(); - ConnectorSentNoMessagesToSink(); // When the sink is ready, the Cast Provider sends a notification to the // connector. The connector will notify both sources that a sink is once @@ -503,14 +386,14 @@ .RetiresOnSaturation(); EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) .RetiresOnSaturation(); - ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); + media_remoter->OnSinkAvailable(); RunUntilIdle(); // When the sink is no longer available, the Cast Provider notifies the // connector, and both sources are then notified the sink is gone. EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); - ProviderLosesSink(); + media_remoter.reset(); RunUntilIdle(); break; @@ -519,23 +402,17 @@ case MOJO_PIPE_CLOSES: // When the Mojo pipes for |other_source| close, this should not affect // the current remoting session. + EXPECT_CALL(*media_remoter, Stop(_)).Times(0); other_source.reset(); other_remoter.reset(); RunUntilIdle(); - ConnectorSentNoMessagesToProvider(); // Now, when the Mojo pipes for |source| close, the Cast Provider will be // notified that the session has stopped. + EXPECT_CALL(*media_remoter, Stop(_)).Times(1).RetiresOnSaturation(); source.reset(); remoter.reset(); RunUntilIdle(); - ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1"); - - // The Cast Provider will detect when the sink is ready for the next - // remoting session, and then notify the connector. However, there are no - // sources to propagate this notification to. - ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); - RunUntilIdle(); break; @@ -544,20 +421,14 @@ // terminated the route from the UI), the source and sink are immediately // cut off from one another. EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); - EXPECT_CALL(*source, OnStopped(RemotingStopReason::ROUTE_TERMINATED)) - .Times(1).RetiresOnSaturation(); EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(0)); - MediaRouterTerminatesRoute(); - RunUntilIdle(); - ConnectorSentNoMessagesToProvider(); - // Furthermore, the connector and Cast Provider are also cut off from one // another and should not be able to exchange messages anymore. Therefore, // the connector will never try to notify the sources that the sink is // available again. EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); - ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); + media_remoter.reset(); RunUntilIdle(); break; @@ -569,7 +440,10 @@ EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE)) .Times(1).RetiresOnSaturation(); - ProviderSaysToRemotingConnector("FAILED_CAST_REMOTING:session=1"); + EXPECT_CALL(*media_remoter, Stop(RemotingStopReason::UNEXPECTED_FAILURE)) + .Times(1) + .RetiresOnSaturation(); + media_remoter->OnError(); RunUntilIdle(); // Since remoting is stopped, any further messaging in either direction @@ -577,26 +451,16 @@ const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); + EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); remoter->SendMessageToSink(message_to_sink); - ProviderPassesMessageFromSink(message_to_source); - RunUntilIdle(); - ConnectorSentNoMessagesToSink(); - - // Later, if whatever caused the external failure has resolved, the Cast - // Provider will notify the connector that the sink is available one - // again. - EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) - .RetiresOnSaturation(); - ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); + media_remoter->SendMessageToSource(message_to_source); RunUntilIdle(); // When the sink is no longer available, the Cast Provider notifies the // connector, and both sources are then notified the sink is gone. EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); - ProviderLosesSink(); + media_remoter.reset(); RunUntilIdle(); break;
diff --git a/chrome/browser/media/router/media_router.h b/chrome/browser/media/router/media_router.h index 00b583e..48b855cc 100644 --- a/chrome/browser/media/router/media_router.h +++ b/chrome/browser/media/router/media_router.h
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/callback_list.h" #include "base/time/time.h" +#include "chrome/browser/media/cast_remoting_connector.h" #include "chrome/browser/media/router/route_message_observer.h" #include "chrome/common/media_router/discovery/media_sink_internal.h" #include "chrome/common/media_router/issue.h" @@ -199,6 +200,14 @@ virtual scoped_refptr<MediaRouteController> GetRouteController( const MediaRoute::Id& route_id) = 0; + // Registers/Unregisters a CastRemotingConnector with the |tab_id|. For a + // given |tab_id|, only one CastRemotingConnector can be registered. The + // registered CastRemotingConnector should be removed before it is destroyed. + virtual void RegisterRemotingSource( + int32_t tab_id, + CastRemotingConnector* remoting_source) = 0; + virtual void UnregisterRemotingSource(int32_t tab_id) = 0; + private: friend class IssuesObserver; friend class MediaSinksObserver;
diff --git a/chrome/browser/media/router/media_router_base.cc b/chrome/browser/media/router/media_router_base.cc index d3ec5e6..e29be4c 100644 --- a/chrome/browser/media/router/media_router_base.cc +++ b/chrome/browser/media/router/media_router_base.cc
@@ -155,4 +155,21 @@ void MediaRouterBase::DetachRouteController(const MediaRoute::Id& route_id, MediaRouteController* controller) {} +void MediaRouterBase::RegisterRemotingSource( + int32_t tab_id, + CastRemotingConnector* remoting_source) { + auto it = remoting_sources_.find(tab_id); + if (it != remoting_sources_.end()) { + DCHECK(remoting_source == it->second); + return; + } + remoting_sources_.emplace(tab_id, remoting_source); +} + +void MediaRouterBase::UnregisterRemotingSource(int32_t tab_id) { + auto it = remoting_sources_.find(tab_id); + DCHECK(it != remoting_sources_.end()); + remoting_sources_.erase(it); +} + } // namespace media_router
diff --git a/chrome/browser/media/router/media_router_base.h b/chrome/browser/media/router/media_router_base.h index c482662..807ac26 100644 --- a/chrome/browser/media/router/media_router_base.h +++ b/chrome/browser/media/router/media_router_base.h
@@ -37,6 +37,10 @@ scoped_refptr<MediaRouteController> GetRouteController( const MediaRoute::Id& route_id) override; + void RegisterRemotingSource(int32_t tab_id, + CastRemotingConnector* remoting_source) override; + void UnregisterRemotingSource(int32_t tab_id) override; + protected: FRIEND_TEST_ALL_PREFIXES(MediaRouterMojoImplTest, PresentationConnectionStateChangedCallback); @@ -73,6 +77,11 @@ std::unique_ptr<PresentationConnectionStateChangedCallbacks>> presentation_connection_state_callbacks_; + // Stores CastRemotingConnectors that can be connected to the MediaRemoter + // for media remoting when MediaRemoter is started. The map uses the tab ID + // as the key. + std::unordered_map<int32_t, CastRemotingConnector*> remoting_sources_; + private: friend class MediaRouterBaseTest; friend class MediaRouterFactory;
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc index fb6ad4cd..ee3c4c6 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
@@ -1021,4 +1021,21 @@ MediaRouterMojoMetrics::RecordMediaRouteControllerCreationResult(success); } +void MediaRouterMojoImpl::OnMediaRemoterCreated( + int32_t tab_id, + media::mojom::MirrorServiceRemoterPtr remoter, + media::mojom::MirrorServiceRemotingSourceRequest source_request) { + DVLOG_WITH_INSTANCE(1) << __func__ << ": tab_id = " << tab_id; + + auto it = remoting_sources_.find(tab_id); + if (it == remoting_sources_.end()) { + LOG(WARNING) << __func__ + << ": No registered remoting source for tab_id = " << tab_id; + return; + } + + CastRemotingConnector* connector = it->second; + connector->ConnectToService(std::move(source_request), std::move(remoter)); +} + } // namespace media_router
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.h b/chrome/browser/media/router/mojo/media_router_mojo_impl.h index 6dbf96e..01cb711 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.h +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.h
@@ -328,6 +328,10 @@ const std::string& route_id, const std::vector<content::PresentationConnectionMessage>& messages) override; + void OnMediaRemoterCreated( + int32_t tab_id, + media::mojom::MirrorServiceRemoterPtr remoter, + media::mojom::MirrorServiceRemotingSourceRequest source_request) override; // Result callback when Mojo terminateRoute is invoked. |route_id| is bound // to the ID of the route that was terminated.
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc index cda6f282..0cf731de 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -218,6 +218,7 @@ PageLoadTracker* MetricsWebContentsObserver::GetTrackerOrNullForRequest( const content::GlobalRequestID& request_id, + content::RenderFrameHost* render_frame_host_or_null, content::ResourceType resource_type, base::TimeTicks creation_time) { if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) { @@ -240,23 +241,33 @@ // Non main frame resources are always associated with the currently // committed load. If the resource request was started before this // navigation then it should be ignored. + if (!committed_load_ || creation_time < committed_load_->navigation_start()) + return nullptr; - // TODO(jkarlin): There is a race here. Consider the following sequence: - // 1. renderer has a committed page A - // 2. navigation is initiated to page B - // 3. page A initiates URLRequests (e.g. in the unload handler) - // 4. page B commits - // 5. the URLRequests initiated by A complete - // In the above example, the URLRequests initiated by A will be attributed - // to page load B. This should be relatively rare but we may want to fix - // this at some point. We could fix this by comparing the URLRequest - // creation time against the committed load's commit time, however more - // investigation is needed to confirm that all cases would be handled - // correctly (for example Link: preloads). - if (committed_load_ && - creation_time >= committed_load_->navigation_start()) { + // Sub-frame resources have a null RFH when browser-side navigation is + // enabled, so we can't perform the RFH check below for them. + // + // TODO(bmcquade): consider tracking GlobalRequestIDs for sub-frame + // navigations in each PageLoadTracker, and performing a lookup for + // sub-frames similar to the main-frame lookup above. + if (resource_type == content::RESOURCE_TYPE_SUB_FRAME) return committed_load_.get(); - } + + // There is a race here: a completed resource for the previously committed + // page can arrive after the new page has committed. In this case, we may + // attribute the resource to the wrong page load. We do our best to guard + // against this by verifying that the RFH for the resource matches the RFH + // for the currently committed load, however there are cases where the same + // RFH is used across page loads (same origin navigations, as well as some + // cross-origin render-initiated navigations). + // + // TODO(crbug.com/738577): use a DocumentId here instead, to eliminate this + // race. + DCHECK(render_frame_host_or_null != nullptr); + content::RenderFrameHost* main_frame_for_resource = + GetMainFrame(render_frame_host_or_null); + if (main_frame_for_resource == web_contents()->GetMainFrame()) + return committed_load_.get(); } return nullptr; } @@ -266,6 +277,7 @@ const net::HostPortPair& host_port_pair, int frame_tree_node_id, const content::GlobalRequestID& request_id, + content::RenderFrameHost* render_frame_host_or_null, content::ResourceType resource_type, bool was_cached, std::unique_ptr<data_reduction_proxy::DataReductionProxyData> @@ -278,8 +290,8 @@ if (!url.SchemeIsHTTPOrHTTPS()) return; - PageLoadTracker* tracker = - GetTrackerOrNullForRequest(request_id, resource_type, creation_time); + PageLoadTracker* tracker = GetTrackerOrNullForRequest( + request_id, render_frame_host_or_null, resource_type, creation_time); if (tracker) { ExtraRequestCompleteInfo extra_request_complete_info( url, host_port_pair, frame_tree_node_id, was_cached, raw_body_bytes,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h index 69eedb2..5d35bf3 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -96,12 +96,14 @@ content::NavigationHandle* navigation_handle); // A resource request completed on the IO thread. This method is invoked on - // the UI thread. + // the UI thread. |render_frame_host_or_null will| be null for main or sub + // frame requests when browser-side navigation is enabled. void OnRequestComplete( const GURL& url, const net::HostPortPair& host_port_pair, int frame_tree_node_id, const content::GlobalRequestID& request_id, + content::RenderFrameHost* render_frame_host_or_null, content::ResourceType resource_type, bool was_cached, std::unique_ptr<data_reduction_proxy::DataReductionProxyData> @@ -156,6 +158,7 @@ // PageLoadTrackers. PageLoadTracker* GetTrackerOrNullForRequest( const content::GlobalRequestID& request_id, + content::RenderFrameHost* render_frame_host_or_null, content::ResourceType resource_type, base::TimeTicks creation_time);
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc index f7ffe1b9..712caed 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -983,6 +983,7 @@ observer()->OnRequestComplete( main_resource_url, net::HostPortPair(), frame_tree_node_id, request_id, + web_contents()->GetMainFrame(), content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, false, nullptr, 0, 0, base::TimeTicks::Now(), net::OK); EXPECT_EQ(1u, loaded_resources().size()); @@ -994,6 +995,7 @@ // specified |request_id| is no longer associated with any tracked page loads. observer()->OnRequestComplete( main_resource_url, net::HostPortPair(), frame_tree_node_id, request_id, + web_contents()->GetMainFrame(), content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, false, nullptr, 0, 0, base::TimeTicks::Now(), net::OK); EXPECT_EQ(1u, loaded_resources().size()); @@ -1008,14 +1010,40 @@ observer()->OnRequestComplete( loaded_resource_url, net::HostPortPair(), web_contents()->GetMainFrame()->GetFrameTreeNodeId(), - content::GlobalRequestID(), content::RESOURCE_TYPE_SCRIPT, false, nullptr, - 0, 0, base::TimeTicks::Now(), net::OK); + content::GlobalRequestID(), web_contents()->GetMainFrame(), + content::RESOURCE_TYPE_SCRIPT, false, nullptr, 0, 0, + base::TimeTicks::Now(), net::OK); EXPECT_EQ(1u, loaded_resources().size()); EXPECT_EQ(loaded_resource_url, loaded_resources().back().url); } TEST_F(MetricsWebContentsObserverTest, + OnLoadedResource_ResourceFromOtherRFHIgnored) { + content::WebContentsTester* web_contents_tester = + content::WebContentsTester::For(web_contents()); + web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); + + // This is a bit of a hack. We want to simulate giving the + // MetricsWebContentsObserver a RenderFrameHost from a previously committed + // page, to verify that resources for RFHs that don't match the currently + // committed RFH are ignored. There isn't a way to hold on to an old RFH (it + // gets cleaned up soon after being navigated away from) so instead we use an + // RFH from another WebContents, as a way to simulate the desired behavior. + content::WebContents* other_web_contents = + content::WebContentsTester::CreateTestWebContents(browser_context(), + nullptr); + observer()->OnRequestComplete( + GURL("http://www.other.com/"), net::HostPortPair(), + other_web_contents->GetMainFrame()->GetFrameTreeNodeId(), + content::GlobalRequestID(), other_web_contents->GetMainFrame(), + content::RESOURCE_TYPE_SCRIPT, false, nullptr, 0, 0, + base::TimeTicks::Now(), net::OK); + + EXPECT_TRUE(loaded_resources().empty()); +} + +TEST_F(MetricsWebContentsObserverTest, OnLoadedResource_IgnoreNonHttpOrHttpsScheme) { content::WebContentsTester* web_contents_tester = content::WebContentsTester::For(web_contents()); @@ -1024,8 +1052,9 @@ observer()->OnRequestComplete( loaded_resource_url, net::HostPortPair(), web_contents()->GetMainFrame()->GetFrameTreeNodeId(), - content::GlobalRequestID(), content::RESOURCE_TYPE_SCRIPT, false, nullptr, - 0, 0, base::TimeTicks::Now(), net::OK); + content::GlobalRequestID(), web_contents()->GetMainFrame(), + content::RESOURCE_TYPE_SCRIPT, false, nullptr, 0, 0, + base::TimeTicks::Now(), net::OK); EXPECT_TRUE(loaded_resources().empty()); }
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc index f68af67..639ead34 100644 --- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
@@ -95,6 +95,7 @@ GURL(kNonAdUrl), net::HostPortPair(), navigation_handle->GetRenderFrameHost()->GetFrameTreeNodeId(), navigation_handle->GetGlobalRequestID(), + navigation_handle->GetRenderFrameHost(), content::RESOURCE_TYPE_MAIN_FRAME, false /* was_cached */, nullptr /* data_reduction_proxy */, 10 * 1024 /* raw_body_bytes */, 0 /* original_network_content_length */, base::TimeTicks::Now(), 0);
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc new file mode 100644 index 0000000..11066e7 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc
@@ -0,0 +1,599 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h" + +#include "base/lazy_instance.h" +#include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_util.h" +#include "net/base/host_port_pair.h" +#include "net/base/ip_address.h" +#include "net/base/net_errors.h" +#include "net/base/url_util.h" +#include "services/metrics/public/cpp/ukm_entry_builder.h" +#include "services/metrics/public/cpp/ukm_recorder.h" +#include "url/gurl.h" + +namespace { +// These constants are used to generate the UMA histograms for local network +// request metrics. If the enums for |DomainType|, |ResourceType|, or |PortType| +// change, the bitwise arithmetic below must also change. +static const int kNumNonlocalhostHistograms = + internal::DOMAIN_TYPE_LOCALHOST << 6 | + internal::RESOURCE_TYPE_LOCALHOST << 1 | true + 1; +static const int kNumLocalhostHistograms = + internal::DOMAIN_TYPE_LOCALHOST << 5 | internal::PORT_TYPE_DEV << 1 | + true + 1; + +// Generates a histogram for a non-localhost resource using the values stored in +// |counts| given a combination of domain type, resource type, and status for +// the resource. +void CreateHistogram(std::map<const std::string, int> counts, + internal::DomainType domain_type, + internal::ResourceType resource_type, + bool status) { + const std::string& histogram_name = internal::GetNonlocalhostHistogramNames() + .at(domain_type) + .at(resource_type) + .at(status); + // Because the macro requires a single value for the maximum histogram index, + // but we use three variables to distinguish histograms, we bitwise + // concatenate them here to uniquely distinguish each combination. If the + // enums for |DomainType| or |ResourceType| change, the bitwise arithmetic + // below must also change. + const int histogram_index = + domain_type << 6 | resource_type << 1 | (status ? 1 : 0); + STATIC_HISTOGRAM_POINTER_GROUP( + histogram_name, histogram_index, kNumNonlocalhostHistograms, + Add(counts[histogram_name]), + base::Histogram::FactoryGet( + histogram_name, + 1, // min value + 1000, // max value + 50, // number of buckets + base::HistogramBase::kUmaTargetedHistogramFlag)); +} + +// Generates a histogram for a localhost resource using the values stored in +// |counts| given a combination of domain type, port type, and status for +// the resource. +void CreateHistogram(std::map<const std::string, int> counts, + internal::DomainType domain_type, + internal::PortType port_type, + bool status) { + const std::string& histogram_name = internal::GetLocalhostHistogramNames() + .at(domain_type) + .at(port_type) + .at(status); + // Because the macro requires a single value for the maximum histogram index, + // but we use three variables to distinguish histograms, we bitwise + // concatenate them here to uniquely distinguish each combination. If the + // enums for |DomainType| or |PortType| change, the bitwise arithmetic + // below must also change. + const int histogram_index = + domain_type << 5 | port_type << 1 | (status ? 1 : 0); + STATIC_HISTOGRAM_POINTER_GROUP( + histogram_name, histogram_index, kNumLocalhostHistograms, + Add(counts[histogram_name]), + base::Histogram::FactoryGet( + histogram_name, + 1, // min value + 1000, // max value + 50, // number of buckets + base::HistogramBase::kUmaTargetedHistogramFlag)); +} + +// TODO(uthakore): Update router regex based on further study. +// Returns true if the IP address matches the following regular expression for +// common router IP addresses: +// "^192\.168\.(0|10?|2)\.(1(00?)?)|^10\.(0|1)\.(0|10?)\.(1(00?)?|2)" +bool IsLikelyRouterIP(net::IPAddress ip_address) { + return ip_address.IsIPv4() && + ((ip_address.bytes()[0] == 192 && ip_address.bytes()[1] == 168 && + (ip_address.bytes()[2] == 0 || ip_address.bytes()[2] == 1 || + ip_address.bytes()[2] == 2 || ip_address.bytes()[2] == 10) && + (ip_address.bytes()[3] == 1 || ip_address.bytes()[3] == 10 || + ip_address.bytes()[3] == 100)) || + (ip_address.bytes()[0] == 10 && + (ip_address.bytes()[1] == 0 || ip_address.bytes()[1] == 1) && + (ip_address.bytes()[2] == 0 || ip_address.bytes()[2] == 1 || + ip_address.bytes()[2] == 10) && + (ip_address.bytes()[3] == 1 || ip_address.bytes()[3] == 10 || + ip_address.bytes()[3] == 100 || ip_address.bytes()[3] == 2))); +} + +// Attempts to get the IP address of a resource request from +// |extra_request_info.host_port_pair|, trying to get it from the URL string in +// |extra_request_info.url| if that fails. +// Sets the values of |resource_ip| and |port| with the extracted IP address and +// port, respectively. +// Returns true if a valid, nonempty IP address was extracted. +bool GetIPAndPort( + const page_load_metrics::ExtraRequestCompleteInfo& extra_request_info, + net::IPAddress* resource_ip, + int* resource_port) { + // If the request was successful, then the IP address should be in + // |extra_request_info|. + bool ip_exists = net::ParseURLHostnameToAddress( + extra_request_info.host_port_pair.host(), resource_ip); + *resource_port = extra_request_info.host_port_pair.port(); + + // If the request failed, it's possible we didn't receive the IP address, + // possibly because domain resolution failed. As a backup, try getting the IP + // from the URL. If none was returned, try matching the hostname from the URL + // itself as it might be an IP address if it is a local network request, which + // is what we care about. + if (!ip_exists && extra_request_info.url.is_valid()) { + if (net::IsLocalhost(extra_request_info.url.HostNoBrackets())) { + *resource_ip = net::IPAddress::IPv4Localhost(); + ip_exists = true; + } else { + ip_exists = net::ParseURLHostnameToAddress(extra_request_info.url.host(), + resource_ip); + } + *resource_port = extra_request_info.url.EffectiveIntPort(); + } + + if (net::IsLocalhost(resource_ip->ToString())) { + *resource_ip = net::IPAddress::IPv4Localhost(); + ip_exists = true; + } + + return ip_exists; +} + +// Getter for the list of mappings for localhost ports that belong to special +// categories that we want to track. +const std::map<uint16_t, internal::PortType>& GetLocalhostPortCategories() { + static base::LazyInstance<std::map<uint16_t, internal::PortType>>::Leaky + localhost_port_categories = LAZY_INSTANCE_INITIALIZER; + if (localhost_port_categories.Get().empty()) { + localhost_port_categories.Get() = { + {80, internal::PORT_TYPE_WEB}, {443, internal::PORT_TYPE_WEB}, + {8000, internal::PORT_TYPE_WEB}, {8008, internal::PORT_TYPE_WEB}, + {8080, internal::PORT_TYPE_WEB}, {8081, internal::PORT_TYPE_WEB}, + {8088, internal::PORT_TYPE_WEB}, {8181, internal::PORT_TYPE_WEB}, + {8888, internal::PORT_TYPE_WEB}, {3306, internal::PORT_TYPE_DB}, + {5432, internal::PORT_TYPE_DB}, {27017, internal::PORT_TYPE_DB}, + {427, internal::PORT_TYPE_PRINT}, {515, internal::PORT_TYPE_PRINT}, + {631, internal::PORT_TYPE_PRINT}, {9100, internal::PORT_TYPE_PRINT}, + {9220, internal::PORT_TYPE_PRINT}, {9500, internal::PORT_TYPE_PRINT}, + {3000, internal::PORT_TYPE_DEV}, {5000, internal::PORT_TYPE_DEV}, + {9000, internal::PORT_TYPE_DEV}, + // TODO(uthakore): Add additional port mappings based on further study. + }; + } + + return localhost_port_categories.Get(); +} + +} // namespace + +namespace internal { + +// UKM event names +const char kUkmPageDomainEventName[] = "PageDomainInfo"; +const char kUkmLocalNetworkRequestsEventName[] = "LocalNetworkRequests"; + +// UKM metric names +const char kUkmDomainTypeName[] = "DomainType"; +const char kUkmResourceTypeName[] = "ResourceType"; +const char kUkmPortTypeName[] = "PortType"; +const char kUkmSuccessfulCountName[] = "Count.Successful"; +const char kUkmFailedCountName[] = "Count.Failed"; + +// Definitions of getters for the histogram names maps. +const std::map<internal::DomainType, + std::map<internal::ResourceType, std::map<bool, std::string>>>& +GetNonlocalhostHistogramNames() { + static base::LazyInstance<std::map< + internal::DomainType, + std::map<internal::ResourceType, std::map<bool, std::string>>>>::Leaky + histogram_names = LAZY_INSTANCE_INITIALIZER; + + if (histogram_names.Get().empty()) { + histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC] + [internal::RESOURCE_TYPE_PRIVATE][true] = + "LocalNetworkRequests.PublicPage.PrivateRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC] + [internal::RESOURCE_TYPE_PRIVATE][false] = + "LocalNetworkRequests.PublicPage.PrivateRequestCount.Failed"; + histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC] + [internal::RESOURCE_TYPE_ROUTER][true] = + "LocalNetworkRequests.PublicPage.RouterRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC] + [internal::RESOURCE_TYPE_ROUTER][false] = + "LocalNetworkRequests.PublicPage.RouterRequestCount.Failed"; + + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::RESOURCE_TYPE_PUBLIC][true] = + "LocalNetworkRequests.PrivatePage.PublicRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::RESOURCE_TYPE_PUBLIC][false] = + "LocalNetworkRequests.PrivatePage.PublicRequestCount.Failed"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET][true] = + "LocalNetworkRequests.PrivatePage.SameSubnetRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET][false] = + "LocalNetworkRequests.PrivatePage.SameSubnetRequestCount.Failed"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET][true] = + "LocalNetworkRequests.PrivatePage." + "DifferentSubnetRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET][false] = + "LocalNetworkRequests.PrivatePage.DifferentSubnetRequestCount.Failed"; + } + + return histogram_names.Get(); +} + +const std::map<internal::DomainType, + std::map<internal::PortType, std::map<bool, std::string>>>& +GetLocalhostHistogramNames() { + static base::LazyInstance<std::map< + internal::DomainType, + std::map<internal::PortType, std::map<bool, std::string>>>>::Leaky + histogram_names = LAZY_INSTANCE_INITIALIZER; + + if (histogram_names.Get().empty()) { + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_WEB][true] = + "LocalNetworkRequests.PublicPage.Localhost." + "WebRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_WEB][false] = + "LocalNetworkRequests.PublicPage.Localhost." + "WebRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DB][true] = + "LocalNetworkRequests.PublicPage.Localhost." + "DatabaseRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DB][false] = + "LocalNetworkRequests.PublicPage.Localhost." + "DatabaseRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_PRINT][true] = + "LocalNetworkRequests.PublicPage.Localhost." + "PrinterRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_PRINT][false] = + "LocalNetworkRequests.PublicPage.Localhost." + "PrinterRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DEV][true] = + "LocalNetworkRequests.PublicPage.Localhost." + "DevelopmentRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DEV][false] = + "LocalNetworkRequests.PublicPage.Localhost." + "DevelopmentRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_OTHER][true] = + "LocalNetworkRequests.PublicPage.Localhost." + "OtherRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_OTHER][false] = + "LocalNetworkRequests.PublicPage.Localhost." + "OtherRequestCount.Failed"; + + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_WEB][true] = + "LocalNetworkRequests.PrivatePage.Localhost." + "WebRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_WEB][false] = + "LocalNetworkRequests.PrivatePage.Localhost." + "WebRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DB][true] = + "LocalNetworkRequests.PrivatePage.Localhost." + "DatabaseRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DB][false] = + "LocalNetworkRequests.PrivatePage.Localhost." + "DatabaseRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_PRINT][true] = + "LocalNetworkRequests.PrivatePage.Localhost." + "PrinterRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::PORT_TYPE_PRINT][false] = + "LocalNetworkRequests.PrivatePage.Localhost." + "PrinterRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DEV][true] = + "LocalNetworkRequests.PrivatePage.Localhost." + "DevelopmentRequestCount.Successful"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DEV][false] = + "LocalNetworkRequests.PrivatePage.Localhost." + "DevelopmentRequestCount.Failed"; + histogram_names + .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_OTHER][true] = + "LocalNetworkRequests.PrivatePage.Localhost." + "OtherRequestCount.Successful"; + histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE] + [internal::PORT_TYPE_OTHER][false] = + "LocalNetworkRequests.PrivatePage.Localhost." + "OtherRequestCount.Failed"; + } + + return histogram_names.Get(); +} + +} // namespace internal + +LocalNetworkRequestsPageLoadMetricsObserver:: + LocalNetworkRequestsPageLoadMetricsObserver() {} +LocalNetworkRequestsPageLoadMetricsObserver:: + ~LocalNetworkRequestsPageLoadMetricsObserver() {} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy +LocalNetworkRequestsPageLoadMetricsObserver::OnCommit( + content::NavigationHandle* navigation_handle, + ukm::SourceId source_id) { + // Upon page load, we want to determine whether the page loaded was a public + // domain or private domain and generate an event describing the domain type. + net::HostPortPair address = navigation_handle->GetSocketAddress(); + + // In cases where the page loaded does not have a socket address or was not a + // network resource, we don't want to track the page load. Such resources will + // fail to parse or return an empty IP address. + if (!net::ParseURLHostnameToAddress(address.host(), &page_ip_address_) || + page_ip_address_.IsZero()) { + return STOP_OBSERVING; + } + + // |IsLocalhost| assumes (and doesn't verify) that any IPv6 address passed + // to it does not have square brackets around it, but |HostPortPair::host| + // retains the brackets, so we need to separately check for IPv6 localhost + // here. + if (net::IsLocalhost(address.host()) || + page_ip_address_ == net::IPAddress::IPv6Localhost()) { + page_domain_type_ = internal::DOMAIN_TYPE_LOCALHOST; + } else if (page_ip_address_.IsReserved()) { + page_domain_type_ = internal::DOMAIN_TYPE_PRIVATE; + // Maps from first byte of an IPv4 address to the number of bits in the + // reserved prefix. This table contains the subset of prefixes defined in + // |IPAddress::IsReservedIPv4| from which we would expect a page load. + // TODO: Refactor this code to remove the table and retrieve the prefix from + // net::IPAddress as per bug 739856. + static const uint8_t kReservedIPv4Prefixes[][2] = { + {10, 8}, {100, 10}, {169, 16}, {172, 12}, {192, 16}, {198, 15}}; + + for (const auto& entry : kReservedIPv4Prefixes) { + // A reserved IP will always be a valid IPv4 or IPv6 address and will + // thus have at least 4 bytes, so [0] is safe here. + if (page_ip_address_.bytes()[0] == entry[0]) { + page_ip_prefix_length_ = entry[1]; + } + } + } else { + page_domain_type_ = internal::DOMAIN_TYPE_PUBLIC; + } + + RecordUkmDomainType(source_id); + + // If the load was localhost, we don't track it because it isn't meaningful + // for our purposes. + return (page_domain_type_ == internal::DOMAIN_TYPE_LOCALHOST) + ? STOP_OBSERVING + : CONTINUE_OBSERVING; +} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy +LocalNetworkRequestsPageLoadMetricsObserver::FlushMetricsOnAppEnterBackground( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) { + // The browser may come back, but there is no guarantee. To be safe, we record + // what we have now and treat changes to this navigation as new page loads. + if (extra_info.did_commit) { + RecordHistograms(); + RecordUkmMetrics(extra_info.source_id); + ClearLocalState(); + } + + return CONTINUE_OBSERVING; +} + +void LocalNetworkRequestsPageLoadMetricsObserver::OnLoadedResource( + const page_load_metrics::ExtraRequestCompleteInfo& extra_request_info) { + net::IPAddress resource_ip; + int resource_port; + + // We can't track anything if we don't have an IP address for the resource. + // We also don't want to track any requests to the page's IP address itself. + if (!GetIPAndPort(extra_request_info, &resource_ip, &resource_port) || + resource_ip.IsZero() || resource_ip == page_ip_address_) { + return; + } + + // We monitor localhost resource requests for both public and private page + // loads. + if (resource_ip == net::IPAddress::IPv4Localhost()) { + if (extra_request_info.net_error != net::OK) { + localhost_request_counts_[resource_port].second++; + } else { + localhost_request_counts_[resource_port].first++; + } + } + // We only track public resource requests for private pages. + else if (resource_ip.IsReserved() || + page_domain_type_ == internal::DOMAIN_TYPE_PRIVATE) { + if (extra_request_info.net_error != net::OK) { + resource_request_counts_[resource_ip].second++; + } else { + resource_request_counts_[resource_ip].first++; + } + } +} + +void LocalNetworkRequestsPageLoadMetricsObserver::OnComplete( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& info) { + if (info.did_commit) { + RecordHistograms(); + RecordUkmMetrics(info.source_id); + } +} + +void LocalNetworkRequestsPageLoadMetricsObserver::ClearLocalState() { + localhost_request_counts_.clear(); + resource_request_counts_.clear(); + requested_resource_types_.reset(); +} + +void LocalNetworkRequestsPageLoadMetricsObserver::RecordHistograms() { + if (page_domain_type_ == internal::DOMAIN_TYPE_LOCALHOST) { + return; + } + ResolveResourceTypes(); + + // Compute the number of requests of each resource type for the loaded page. + std::map<const std::string, int> counts; + for (const auto& entry : resource_request_counts_) { + counts[internal::GetNonlocalhostHistogramNames() + .at(page_domain_type_) + .at(requested_resource_types_->at(entry.first)) + .at(true)] += entry.second.first; + counts[internal::GetNonlocalhostHistogramNames() + .at(page_domain_type_) + .at(requested_resource_types_->at(entry.first)) + .at(false)] += entry.second.second; + } + + for (const auto& entry : localhost_request_counts_) { + counts[internal::GetLocalhostHistogramNames() + .at(page_domain_type_) + .at(DeterminePortType(entry.first)) + .at(true)] += entry.second.first; + counts[internal::GetLocalhostHistogramNames() + .at(page_domain_type_) + .at(DeterminePortType(entry.first)) + .at(false)] += entry.second.second; + } + + // Log a histogram for each type of resource depending on the domain type of + // the page load. + if (page_domain_type_ == internal::DOMAIN_TYPE_PUBLIC) { + for (auto resource_type : + {internal::RESOURCE_TYPE_PRIVATE, internal::RESOURCE_TYPE_ROUTER}) { + CreateHistogram(counts, page_domain_type_, resource_type, true); + CreateHistogram(counts, page_domain_type_, resource_type, false); + } + } else { + DCHECK_EQ(page_domain_type_, internal::DOMAIN_TYPE_PRIVATE); + for (auto resource_type : {internal::RESOURCE_TYPE_PUBLIC, + internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, + internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET}) { + CreateHistogram(counts, page_domain_type_, resource_type, true); + CreateHistogram(counts, page_domain_type_, resource_type, false); + } + } + for (auto port_type : {internal::PORT_TYPE_WEB, internal::PORT_TYPE_DB, + internal::PORT_TYPE_PRINT, internal::PORT_TYPE_DEV, + internal::PORT_TYPE_OTHER}) { + CreateHistogram(counts, page_domain_type_, port_type, true); + CreateHistogram(counts, page_domain_type_, port_type, false); + } +} + +internal::ResourceType +LocalNetworkRequestsPageLoadMetricsObserver::DetermineResourceType( + net::IPAddress resource_ip) { + if (page_domain_type_ == internal::DOMAIN_TYPE_PUBLIC) { + DCHECK(resource_ip.IsReserved()); + return IsLikelyRouterIP(resource_ip) ? internal::RESOURCE_TYPE_ROUTER + : internal::RESOURCE_TYPE_PRIVATE; + } + + DCHECK_EQ(internal::DOMAIN_TYPE_PRIVATE, page_domain_type_); + if (resource_ip.IsReserved()) { // PRIVATE + const bool is_same_subnet = + net::CommonPrefixLength(page_ip_address_, resource_ip) >= + page_ip_prefix_length_; + return is_same_subnet ? internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET + : internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET; + } + return internal::RESOURCE_TYPE_PUBLIC; // PUBLIC +} + +internal::PortType +LocalNetworkRequestsPageLoadMetricsObserver::DeterminePortType(int port) { + auto lookup = GetLocalhostPortCategories().find(port); + if (lookup == GetLocalhostPortCategories().end()) { + return internal::PORT_TYPE_OTHER; + } else { + return lookup->second; + } +} + +void LocalNetworkRequestsPageLoadMetricsObserver::ResolveResourceTypes() { + // Lazy instantiation. + if (requested_resource_types_) { + return; + } + + requested_resource_types_ = + base::MakeUnique<std::map<net::IPAddress, internal::ResourceType>>(); + for (const auto& entry : resource_request_counts_) { + requested_resource_types_->insert( + {entry.first, DetermineResourceType(entry.first)}); + } +} + +void LocalNetworkRequestsPageLoadMetricsObserver::RecordUkmMetrics( + ukm::SourceId source_id) { + if (page_domain_type_ == internal::DOMAIN_TYPE_LOCALHOST || + g_browser_process->ukm_recorder() == nullptr) { + return; + } + + ResolveResourceTypes(); + + // Log an entry for each non-localhost resource (one per IP address). + for (const auto& entry : resource_request_counts_) { + ukm::UkmRecorder* ukm_recorder = g_browser_process->ukm_recorder(); + std::unique_ptr<ukm::UkmEntryBuilder> builder = + ukm_recorder->GetEntryBuilder( + source_id, internal::kUkmLocalNetworkRequestsEventName); + builder->AddMetric( + internal::kUkmResourceTypeName, + static_cast<int>(requested_resource_types_->at(entry.first))); + builder->AddMetric(internal::kUkmSuccessfulCountName, entry.second.first); + builder->AddMetric(internal::kUkmFailedCountName, entry.second.second); + } + + // Log an entry for each localhost resource (one per port). + for (const auto& entry : localhost_request_counts_) { + ukm::UkmRecorder* ukm_recorder = g_browser_process->ukm_recorder(); + std::unique_ptr<ukm::UkmEntryBuilder> builder = + ukm_recorder->GetEntryBuilder( + source_id, internal::kUkmLocalNetworkRequestsEventName); + builder->AddMetric(internal::kUkmResourceTypeName, + static_cast<int>(internal::RESOURCE_TYPE_LOCALHOST)); + builder->AddMetric(internal::kUkmPortTypeName, + static_cast<int>(DeterminePortType(entry.first))); + builder->AddMetric(internal::kUkmSuccessfulCountName, entry.second.first); + builder->AddMetric(internal::kUkmFailedCountName, entry.second.second); + } +} + +void LocalNetworkRequestsPageLoadMetricsObserver::RecordUkmDomainType( + ukm::SourceId source_id) { + ukm::UkmRecorder* ukm_recorder = g_browser_process->ukm_recorder(); + if (!ukm_recorder) { + return; + } + + std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_recorder->GetEntryBuilder( + source_id, internal::kUkmPageDomainEventName); + builder->AddMetric(internal::kUkmDomainTypeName, + static_cast<int>(page_domain_type_)); +}
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h new file mode 100644 index 0000000..e503c64 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h
@@ -0,0 +1,134 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_LOCAL_NETWORK_REQUESTS_PAGE_LOAD_METRICS_OBSERVER_H_ +#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_LOCAL_NETWORK_REQUESTS_PAGE_LOAD_METRICS_OBSERVER_H_ + +#include <map> +#include <memory> +#include <string> +#include <utility> + +#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" +#include "net/base/ip_address.h" + +namespace internal { + +// The domain type of the IP address of the loaded page. We use these to +// determine what classes of resource request metrics to collect. +enum DomainType { + DOMAIN_TYPE_UNKNOWN = 0, + DOMAIN_TYPE_PUBLIC = 1, + DOMAIN_TYPE_PRIVATE = 2, + DOMAIN_TYPE_LOCALHOST = 4, +}; + +// The type of the IP address of the loaded resource. +enum ResourceType { + RESOURCE_TYPE_PUBLIC = 0, + RESOURCE_TYPE_PRIVATE = 1, + RESOURCE_TYPE_LOCAL_SAME_SUBNET = 2, + RESOURCE_TYPE_LOCAL_DIFF_SUBNET = 4, + RESOURCE_TYPE_ROUTER = 8, + RESOURCE_TYPE_LOCALHOST = 16, +}; + +// The types of services to distinguish between when collecting local network +// request metrics. +enum PortType { + PORT_TYPE_WEB = 1, + PORT_TYPE_DB = 2, + PORT_TYPE_PRINT = 4, + PORT_TYPE_DEV = 8, + PORT_TYPE_OTHER = 0, +}; + +// Exposed for tests. +extern const char kUkmPageDomainEventName[]; +extern const char kUkmLocalNetworkRequestsEventName[]; + +extern const char kUkmDomainTypeName[]; +extern const char kUkmResourceTypeName[]; +extern const char kUkmPortTypeName[]; +extern const char kUkmSuccessfulCountName[]; +extern const char kUkmFailedCountName[]; + +// For simple access during UMA histogram logging, the names are in a +// multidimensional map indexed by [DomainType][ResourceType][Status]. +const std::map<DomainType, std::map<ResourceType, std::map<bool, std::string>>>& +GetNonlocalhostHistogramNames(); +// For localhost histogram names, the map is indexed by +// [DomainType][PortType][Status]. +const std::map<DomainType, std::map<PortType, std::map<bool, std::string>>>& +GetLocalhostHistogramNames(); + +} // namespace internal + +// This observer is for observing local network requests. +// TODO(uthakore): Add description. +class LocalNetworkRequestsPageLoadMetricsObserver + : public page_load_metrics::PageLoadMetricsObserver { + using SuccessFailCounts = std::pair<uint32_t, uint32_t>; + + public: + LocalNetworkRequestsPageLoadMetricsObserver(); + ~LocalNetworkRequestsPageLoadMetricsObserver() override; + + // page_load_metrics::PageLoadMetricsObserver + ObservePolicy OnCommit(content::NavigationHandle* navigation_handle, + ukm::SourceId source_id) override; + ObservePolicy FlushMetricsOnAppEnterBackground( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) override; + void OnLoadedResource(const page_load_metrics::ExtraRequestCompleteInfo& + extra_request_info) override; + void OnComplete(const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& info) override; + + private: + // Clears all local resource request counts. Only used if we decide to log + // metrics but the observer may stay in scope and capture additional resource + // requests. + void ClearLocalState(); + // Determines the resource type for the |ip_address| based on the page load + // type. + internal::ResourceType DetermineResourceType(net::IPAddress ip_address); + // Determines the port type for the localhost |port|. + internal::PortType DeterminePortType(int port); + // Resolves the resource types to report for all IP addresses in + // |resource_request_counts_|. + void ResolveResourceTypes(); + + void RecordUkmDomainType(ukm::SourceId source_id); + void RecordHistograms(); + void RecordUkmMetrics(ukm::SourceId source_id); + + // Stores the counts of resource requests for each non-localhost IP address as + // pairs of (successful, failed) request counts. + std::map<net::IPAddress, SuccessFailCounts> resource_request_counts_; + + std::unique_ptr<std::map<net::IPAddress, internal::ResourceType>> + requested_resource_types_; + + // Stores the counts of resource requests for each localhost port as + // pairs of (successful, failed) request counts. + std::map<int, SuccessFailCounts> localhost_request_counts_; + + // The page load type. This is used to determine what resource requests to + // monitor while the page is committed and to determine the UMA histogram name + // to use. + internal::DomainType page_domain_type_ = internal::DOMAIN_TYPE_UNKNOWN; + + // The IP address of the page that was loaded. + net::IPAddress page_ip_address_; + + // For private page loads, the IP prefix defining the largest reserved subnet + // the page could belong to. Used to distinguish between same subnet and + // different subnet private network queries. + size_t page_ip_prefix_length_ = 0; + + DISALLOW_COPY_AND_ASSIGN(LocalNetworkRequestsPageLoadMetricsObserver); +}; + +#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_LOCAL_NETWORK_REQUESTS_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc new file mode 100644 index 0000000..41a8ef0 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc
@@ -0,0 +1,893 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h" + +#include <vector> + +#include "base/memory/ptr_util.h" +#include "base/test/histogram_tester.h" +#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_util.h" +#include "components/ukm/ukm_source.h" +#include "content/public/browser/global_request_id.h" +#include "content/public/common/resource_type.h" +#include "content/public/test/navigation_simulator.h" +#include "net/base/host_port_pair.h" +#include "net/base/ip_address.h" +#include "net/base/net_errors.h" +#include "url/gurl.h" + +namespace internal { + +typedef struct { + char* url; + char* host_ip; + uint16_t port; +} PageAddressInfo; + +typedef struct { + internal::ResourceType resource_type; + internal::PortType port_type; + int success_count, failed_count; +} UkmMetricInfo; + +static const PageAddressInfo + kPublicPage = {(char*)"https://foo.com/", (char*)"216.58.195.78", 443}, + kPublicPageIPv6 = {(char*)"https://google.com/", + (char*)"[2607:f8b0:4005:809::200e]", 443}, + kPrivatePage = {(char*)"http://test.local/", (char*)"192.168.10.123", 80}, + kLocalhostPage = {(char*)"http://localhost/", (char*)"127.0.0.1", 80}, + kLocalhostPageIPv6 = {(char*)"http://[::1]/", (char*)"[::1]", 80}, + kPublicRequest1 = {(char*)"http://bar.com/", (char*)"100.150.200.250", 80}, + kPublicRequest2 = {(char*)"https://www.baz.com/", (char*)"192.10.20.30", + 443}, + kSameSubnetRequest1 = {(char*)"http://test2.local:9000/", + (char*)"192.168.10.200", 9000}, + kSameSubnetRequest2 = {(char*)"http://test2.local:8000/index.html", + (char*)"192.168.10.200", 8000}, + kSameSubnetRequest3 = {(char*)"http://test2.local:8000/bar.html", + (char*)"192.168.10.200", 8000}, + kDiffSubnetRequest1 = {(char*)"http://10.0.10.200/", (char*)"10.0.10.200", + 80}, + kDiffSubnetRequest2 = {(char*)"http://172.16.0.85:8181/", + (char*)"172.16.0.85", 8181}, + kDiffSubnetRequest3 = {(char*)"http://10.15.20.25:12345/", + (char*)"10.15.20.25", 12345}, + kDiffSubnetRequest4 = {(char*)"http://172.31.100.20:515/", + (char*)"172.31.100.20", 515}, + kLocalhostRequest1 = {(char*)"http://localhost:8080/", (char*)"127.0.0.1", + 8080}, // WEB + kLocalhostRequest2 = {(char*)"http://127.0.1.1:3306/", (char*)"127.0.1.1", + 3306}, // DB + kLocalhostRequest3 = {(char*)"http://localhost:515/", (char*)"127.0.2.1", + 515}, // PRINT + kLocalhostRequest4 = {(char*)"http://127.100.150.200:9000/", + (char*)"127.100.150.200", 9000}, // DEV + kLocalhostRequest5 = {(char*)"http://127.0.0.1:9876/", (char*)"127.0.0.1", + 9876}, // OTHER + kRouterRequest1 = {(char*)"http://10.0.0.1/", (char*)"10.0.0.1", 80}, + kRouterRequest2 = {(char*)"https://192.168.10.1/", (char*)"192.168.10.1", + 443}; + +} // namespace internal + +class LocalNetworkRequestsPageLoadMetricsObserverTest + : public page_load_metrics::PageLoadMetricsObserverTestHarness { + protected: + void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override { + tracker->AddObserver( + base::MakeUnique<LocalNetworkRequestsPageLoadMetricsObserver>()); + } + + void SetUp() override { + page_load_metrics::PageLoadMetricsObserverTestHarness::SetUp(); + } + + void SimulateNavigateAndCommit(const internal::PageAddressInfo& page) { + GURL url(page.url); + net::HostPortPair socket_address(page.host_ip, page.port); + + navigation_simulator_ = + content::NavigationSimulator::CreateRendererInitiated(url, main_rfh()); + navigation_simulator_->Start(); + navigation_simulator_->SetSocketAddress(socket_address); + navigation_simulator_->Commit(); + } + + void SimulateLoadedSuccessfulResource( + const internal::PageAddressInfo& resource) { + SimulateLoadedResource(resource, 0); + } + + void SimulateLoadedFailedResource(const internal::PageAddressInfo& resource) { + SimulateLoadedResource(resource, net::ERR_CONNECTION_REFUSED); + } + + void SimulateLoadedResource(const internal::PageAddressInfo& resource, + const int net_error) { + page_load_metrics::ExtraRequestCompleteInfo request_info( + GURL(resource.url), net::HostPortPair(resource.host_ip, resource.port), + -1 /* frame_tree_node_id */, !net_error /* was_cached */, + (net_error ? 1024 * 20 : 0) /* raw_body_bytes */, + 0 /* original_network_content_length */, + nullptr /* data_reduction_proxy_data */, + content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, net_error); + + PageLoadMetricsObserverTestHarness::SimulateLoadedResource( + request_info, navigation_simulator_->GetGlobalRequestID()); + } + + void NavigateToPageAndLoadResources( + const internal::PageAddressInfo& page, + const std::vector<std::pair<internal::PageAddressInfo, bool>>& + resources_and_statuses) { + SimulateNavigateAndCommit(page); + for (size_t i = 0; i < resources_and_statuses.size(); ++i) { + if (resources_and_statuses[i].second) { + SimulateLoadedSuccessfulResource(resources_and_statuses[i].first); + } else { + SimulateLoadedFailedResource(resources_and_statuses[i].first); + } + } + DeleteContents(); + } + + const content::GlobalRequestID GetGlobalRequestID() { + DCHECK(navigation_simulator_); + return navigation_simulator_->GetGlobalRequestID(); + } + + // Helper functions to verify that particular slices of UMA histograms are + // empty. + void ExpectEmptyHistograms(internal::DomainType domain_type) { + for (const auto& port : + internal::GetLocalhostHistogramNames().at(domain_type)) { + for (const auto& histogramName : port.second) { + histogram_tester().ExpectUniqueSample(histogramName.second, 0, 1); + } + } + for (const auto& resource : + internal::GetNonlocalhostHistogramNames().at(domain_type)) { + for (const auto& histogramName : resource.second) { + histogram_tester().ExpectUniqueSample(histogramName.second, 0, 1); + } + } + } + + void ExpectNoHistograms() { + for (const auto& domain : internal::GetLocalhostHistogramNames()) { + for (const auto& port : domain.second) { + for (const auto& status : port.second) { + histogram_tester().ExpectTotalCount(status.second, 0); + } + } + } + for (const auto& domain : internal::GetNonlocalhostHistogramNames()) { + for (const auto& resource : domain.second) { + for (const auto& status : resource.second) { + histogram_tester().ExpectTotalCount(status.second, 0); + } + } + } + } + + void ExpectUkmPageDomainMetric(const internal::PageAddressInfo& page, + const internal::DomainType domain_type) { + EXPECT_EQ(1ul, ukm_tester().sources_count()); + const ukm::UkmSource* source = ukm_tester().GetSourceForUrl(page.url); + EXPECT_EQ(GURL(page.url), source->url()); + + ukm_tester().ExpectEntry( + *source, internal::kUkmPageDomainEventName, + {{internal::kUkmDomainTypeName, static_cast<int>(domain_type)}}); + } + + void ExpectMetricsAndHistograms( + const internal::PageAddressInfo& page, + const std::vector<internal::UkmMetricInfo>& expected_metrics, + const std::map<std::string, int>& expected_histograms) { + // The page domain info UKM entry will always be created, so we expect that + // there should be one more UKM entry than the expected number of metrics + // entries. + EXPECT_EQ(expected_metrics.size() + 1, ukm_tester().entries_count()); + + const ukm::UkmSource* source = ukm_tester().GetSourceForUrl(page.url); + for (auto entry : expected_metrics) { + std::vector<std::pair<const char*, int64_t>> metric_values = { + {internal::kUkmResourceTypeName, entry.resource_type}, + {internal::kUkmSuccessfulCountName, entry.success_count}, + {internal::kUkmFailedCountName, entry.failed_count}}; + if (entry.resource_type == internal::RESOURCE_TYPE_LOCALHOST) { + // Localhost page load + metric_values.push_back( + {internal::kUkmPortTypeName, static_cast<int>(entry.port_type)}); + } + ukm_tester().ExpectEntry( + *source, internal::kUkmLocalNetworkRequestsEventName, metric_values); + } + + // Should have generated UMA histograms for all requests made. + for (auto hist : expected_histograms) { + histogram_tester().ExpectUniqueSample(hist.first, hist.second, 1); + } + } + + private: + std::unique_ptr<content::NavigationSimulator> navigation_simulator_; +}; + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, NoMetrics) { + EXPECT_EQ(0ul, ukm_tester().sources_count()); + EXPECT_EQ(0ul, ukm_tester().entries_count()); + + // Sanity check + ExpectNoHistograms(); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPageIPv6PublicRequests) { + // Navigate to a public page and make only public resource requests. + const internal::PageAddressInfo& page = internal::kPublicPageIPv6; + NavigateToPageAndLoadResources(page, {{internal::kPublicRequest1, true}, + {internal::kPublicPageIPv6, true}}); + + // Should generate only a domain type UKM entry and nothing else. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + ExpectEmptyHistograms(internal::DOMAIN_TYPE_PUBLIC); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPagePublicRequests) { + // Navigate to a public page and make only public resource requests. + const internal::PageAddressInfo& page = internal::kPublicPage; + NavigateToPageAndLoadResources(page, {{internal::kPublicRequest1, true}, + {internal::kPublicRequest2, true}, + {internal::kPublicPageIPv6, true}}); + + // Should generate only a domain type UKM entry and nothing else. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + ExpectEmptyHistograms(internal::DOMAIN_TYPE_PUBLIC); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PrivatePageSelfRequests) { + // Navigate to a private page and make resource requests only to the page + // itself. + const internal::PageAddressInfo& page = internal::kSameSubnetRequest1; + NavigateToPageAndLoadResources(page, {{internal::kSameSubnetRequest2, true}, + {internal::kSameSubnetRequest3, false}, + {page, true}}); + + // Should generate only a domain type UKM entry and nothing else. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE); + ExpectEmptyHistograms(internal::DOMAIN_TYPE_PRIVATE); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageNoRequests) { + // Navigate to a private page and make no resource requests. + const internal::PageAddressInfo& page = internal::kPrivatePage; + NavigateToPageAndLoadResources( + page, std::vector<std::pair<internal::PageAddressInfo, bool>>{}); + + // Should generate only a domain type UKM entry and nothing else. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE); + ExpectEmptyHistograms(internal::DOMAIN_TYPE_PRIVATE); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, LocalhostPage) { + // Navigate to a localhost page and make some arbitrary resource requests. + const internal::PageAddressInfo& page = internal::kLocalhostPage; + NavigateToPageAndLoadResources(page, {{internal::kPublicRequest1, true}, + {internal::kPublicRequest2, false}, + {internal::kSameSubnetRequest1, true}, + {internal::kLocalhostRequest5, true}}); + + // Should generate only a domain type UKM entry and nothing else. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_LOCALHOST); + ExpectNoHistograms(); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, LocalhostPageIPv6) { + // Navigate to a localhost page with an IPv6 address and make some arbitrary + // resource requests. + const internal::PageAddressInfo& page = internal::kLocalhostPageIPv6; + NavigateToPageAndLoadResources(page, {{internal::kPublicRequest1, false}, + {internal::kLocalhostRequest2, true}, + {internal::kDiffSubnetRequest1, false}, + {internal::kLocalhostRequest4, true}}); + + // Should generate only a domain type UKM entry and nothing else. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_LOCALHOST); + ExpectNoHistograms(); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPageAllSuccessfulRequests) { + // Navigate to a public page and make successful resource requests to all + // resource types. + const internal::PageAddressInfo& page = internal::kPublicPage; + NavigateToPageAndLoadResources(page, {{internal::kPublicPage, true}, + {internal::kPublicPageIPv6, true}, + {internal::kPrivatePage, true}, + {internal::kLocalhostPage, true}, + {internal::kLocalhostPageIPv6, true}, + {internal::kPublicRequest1, true}, + {internal::kPublicRequest2, true}, + {internal::kSameSubnetRequest1, true}, + {internal::kSameSubnetRequest2, true}, + {internal::kSameSubnetRequest3, true}, + {internal::kDiffSubnetRequest1, true}, + {internal::kDiffSubnetRequest2, true}, + {internal::kLocalhostRequest1, true}, + {internal::kLocalhostRequest2, true}, + {internal::kLocalhostRequest3, true}, + {internal::kLocalhostRequest4, true}, + {internal::kLocalhostRequest5, true}, + {internal::kRouterRequest1, true}, + {internal::kRouterRequest2, true}}); + + // Should now have generated UKM entries for each of the types of resources + // requested except for the public resources. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + + // We should now see UKM entries and UMA histograms for each of the types of + // resources requested except for public resources. + ExpectMetricsAndHistograms( + page, + // List of expected UKM metric values. + { + {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1, + 0}, // 10.0.0.1:80 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, + 0}, // 10.0.10.200:80 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, + 0}, // 172.16.0.85:8181 + {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1, + 0}, // 192.168.10.1:443 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, + 0}, // 192.168.10.123:80 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 3, + 0}, // 192.168.10.200:8000 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 2, + 0}, // 127.0.0.1:80 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_PRINT, 1, + 0}, // 127.0.2.1:515 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 1, + 0}, // 127.0.1.1:3306 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 1, + 0}, // 127.0.0.1:8080 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV, 1, + 0}, // 127.100.150.200:9000 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 1, + 0}, // 127.0.0.1:9876 + }, + // List of expected nonzero UMA histogram values. + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_ROUTER) + .at(true), + 2}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_PRIVATE) + .at(true), + 6}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_WEB) + .at(true), + 3}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_PRINT) + .at(true), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_DB) + .at(true), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_DEV) + .at(true), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_OTHER) + .at(true), + 1}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PrivatePageAllSuccessfulRequests) { + // Navigate to a private page and make successful resource requests to all + // resource types. + const internal::PageAddressInfo& page = internal::kPrivatePage; + NavigateToPageAndLoadResources(page, {{internal::kPublicPage, true}, + {internal::kPublicPageIPv6, true}, + {internal::kPrivatePage, true}, + {internal::kLocalhostPage, true}, + {internal::kLocalhostPageIPv6, true}, + {internal::kPublicRequest1, true}, + {internal::kPublicRequest2, true}, + {internal::kSameSubnetRequest1, true}, + {internal::kSameSubnetRequest2, true}, + {internal::kSameSubnetRequest3, true}, + {internal::kDiffSubnetRequest1, true}, + {internal::kDiffSubnetRequest2, true}, + {internal::kLocalhostRequest1, true}, + {internal::kLocalhostRequest2, true}, + {internal::kLocalhostRequest3, true}, + {internal::kLocalhostRequest4, true}, + {internal::kLocalhostRequest5, true}, + {internal::kRouterRequest1, true}, + {internal::kRouterRequest2, true}}); + + // Should now have generated UKM entries for each of the types of resources + // requested except for the public resources. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE); + + // We should now see UKM entries and UMA histograms for each of the types of + // resources requested except for the request to the page itself. + ExpectMetricsAndHistograms( + page, + // List of expected UKM metric values. + { + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 1, 0}, // 10.0.0.1:80 + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 1, 0}, // 10.0.10.200:80 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1, + 0}, // 100.150.200.250:80 + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 1, 0}, // 172.16.0.85:8181 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1, + 0}, // 192.10.20.30:443 + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB, + 1, 0}, // 192.168.10.1:443 + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB, + 3, 0}, // 192.168.10.200:8000 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1, + 0}, // 216.58.195.78:443 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1, + 0}, // [2607:f8b0:4005:809::200e]:443 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 2, + 0}, // 127.0.0.1:80 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_PRINT, 1, + 0}, // 127.0.2.1:515 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 1, + 0}, // 127.0.1.1:3306 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 1, + 0}, // 127.0.0.1:8080 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV, 1, + 0}, // 127.100.150.200:9000 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 1, + 0}, // 127.0.0.1:9876 + }, + // List of expected nonzero UMA histogram values. + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_PUBLIC) + .at(true), + 4}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET) + .at(true), + 3}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET) + .at(true), + 4}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_WEB) + .at(true), + 3}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_PRINT) + .at(true), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_DB) + .at(true), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_DEV) + .at(true), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_OTHER) + .at(true), + 1}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PrivatePageAllFailedRequests) { + // Navigate to a private page and make successful resource requests to all + // resource types. + const internal::PageAddressInfo& page = internal::kPrivatePage; + NavigateToPageAndLoadResources(page, {{internal::kPublicPage, false}, + {internal::kPublicPageIPv6, false}, + {internal::kPrivatePage, false}, + {internal::kLocalhostPage, false}, + {internal::kLocalhostPageIPv6, false}, + {internal::kPublicRequest1, false}, + {internal::kPublicRequest2, false}, + {internal::kSameSubnetRequest1, false}, + {internal::kSameSubnetRequest2, false}, + {internal::kSameSubnetRequest3, false}, + {internal::kDiffSubnetRequest1, false}, + {internal::kDiffSubnetRequest2, false}, + {internal::kLocalhostRequest1, false}, + {internal::kLocalhostRequest2, false}, + {internal::kLocalhostRequest3, false}, + {internal::kLocalhostRequest4, false}, + {internal::kLocalhostRequest5, false}, + {internal::kRouterRequest1, false}, + {internal::kRouterRequest2, false}}); + + // Should now have generated UKM entries for each of the types of resources + // requested except for the public resources. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE); + + ExpectMetricsAndHistograms( + page, + // List of expected UKM metric values. + { + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 10.0.0.1:80 + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 10.0.10.200:80 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0, + 1}, // 100.150.200.250:80 + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 172.16.0.85:8181 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0, + 1}, // 192.10.20.30:443 + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 192.168.10.1:443 + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB, + 0, 3}, // 192.168.10.200:8000 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0, + 1}, // 216.58.195.78:443 + {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0, + 1}, // [2607:f8b0:4005:809::200e]:443 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 0, + 2}, // 127.0.0.1:80 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_PRINT, 0, + 1}, // 127.0.2.1:515 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 0, + 1}, // 127.0.1.1:3306 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 0, + 1}, // 127.0.0.1:8080 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV, 0, + 1}, // 127.100.150.200:9000 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 0, + 1}, // 127.0.0.1:9876 + }, + // List of expected nonzero UMA histogram values. + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_PUBLIC) + .at(false), + 4}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET) + .at(false), + 3}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET) + .at(false), + 4}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_WEB) + .at(false), + 3}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_PRINT) + .at(false), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_DB) + .at(false), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_DEV) + .at(false), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::PORT_TYPE_OTHER) + .at(false), + 1}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPageMixedStatusRequests) { + // Navigate to a public page and make mixed status resource requests. + const internal::PageAddressInfo& page = internal::kPublicPage; + NavigateToPageAndLoadResources(page, {{internal::kPublicRequest1, true}, + {internal::kSameSubnetRequest1, true}, + {internal::kLocalhostRequest2, false}, + {internal::kDiffSubnetRequest2, true}, + {internal::kLocalhostRequest5, false}, + {internal::kDiffSubnetRequest2, false}, + {internal::kRouterRequest1, true}}); + + // Should now have generated UKM entries for each of the types of resources + // requested except for the public resources. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + + ExpectMetricsAndHistograms( + page, + // List of expected UKM metric values. + { + {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1, + 0}, // 10.0.0.1:80 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, + 1}, // 172.16.0.85:8181 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_DEV, 1, + 0}, // 192.168.10.200:8000 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 0, + 1}, // 127.0.1.1:3306 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 0, + 1}, // 127.0.0.1:9876 + }, + // List of expected nonzero UMA histogram values. + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_ROUTER) + .at(true), + 1}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_PRIVATE) + .at(true), + 2}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_PRIVATE) + .at(false), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_DB) + .at(false), + 1}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_OTHER) + .at(false), + 1}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPageLargeNumberOfRequests) { + // This test also verifies the sequence and timing of UKM metric generation. + + // Navigate to a public page with an IPv6 address. + const internal::PageAddressInfo& page = internal::kPublicPageIPv6; + SimulateNavigateAndCommit(page); + + // Should generate only a domain type UKM entry by this point. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + + // Make 100 each of many different types of requests, with 1000 of a single + // type. + std::vector<std::pair<internal::PageAddressInfo, bool>> requests = { + {internal::kPublicRequest1, true}, + {internal::kLocalhostPage, true}, + {internal::kLocalhostPageIPv6, false}, + {internal::kSameSubnetRequest1, false}, + {internal::kDiffSubnetRequest2, false}, + }; + for (auto request : requests) { + for (int i = 0; i < 100; ++i) { + SimulateLoadedResource(request.first, (request.second ? 0 : -1)); + } + } + for (int i = 0; i < 1000; ++i) { + SimulateLoadedSuccessfulResource(internal::kDiffSubnetRequest1); + } + + // At this point, we should still only see the domain type UKM entry. + EXPECT_EQ(1ul, ukm_tester().entries_count()); + + // Close the page. + DeleteContents(); + + ExpectMetricsAndHistograms( + page, + // List of expected UKM metric values. + { + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1000, + 0}, // 10.0.10.200:80 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 0, + 100}, // 172.16.0.85:8181 + {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_DEV, 0, + 100}, // 192.168.10.200:9000 + {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 100, + 100}, // 127.0.0.1:80 + }, + // List of expected nonzero UMA histogram values. + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_PRIVATE) + .at(true), + 1000}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_PRIVATE) + .at(false), + 200}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_WEB) + .at(true), + 100}, + {internal::GetLocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::PORT_TYPE_WEB) + .at(false), + 100}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPageRequestIpInUrlOnly) { + const internal::PageAddressInfo& page = internal::kPublicPage; + SimulateNavigateAndCommit(page); + + // Load a resource that has the IP address in the URL but returned an empty + // socket address for some reason. + PageLoadMetricsObserverTestHarness::SimulateLoadedResource( + { + GURL(internal::kDiffSubnetRequest2.url), net::HostPortPair(), + -1 /* frame_tree_node_id */, true /* was_cached */, + 1024 * 20 /* raw_body_bytes */, + 0 /* original_network_content_length */, + nullptr /* data_reduction_proxy_data */, + content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, 0, + }, + GetGlobalRequestID()); + DeleteContents(); + + // We should still see a UKM entry and UMA histogram for the resource request. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + ExpectMetricsAndHistograms( + page, {{internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, 0}}, + {{internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PUBLIC) + .at(internal::RESOURCE_TYPE_PRIVATE) + .at(true), + 1}}); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, + PublicPageRequestIpNotPresent) { + const internal::PageAddressInfo& page = internal::kPublicPage; + SimulateNavigateAndCommit(page); + + // Load a resource that doesn't have the IP address in the URL and returned an + // empty socket address (e.g., failed DNS resolution). + PageLoadMetricsObserverTestHarness::SimulateLoadedResource( + { + GURL(internal::kPrivatePage.url), net::HostPortPair(), + -1 /* frame_tree_node_id */, false /* was_cached */, + 0 /* raw_body_bytes */, 0 /* original_network_content_length */, + nullptr /* data_reduction_proxy_data */, + content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, -20, + }, + GetGlobalRequestID()); + DeleteContents(); + + // We shouldn't see any UKM entries or UMA histograms this time. + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC); + ExpectEmptyHistograms(internal::DOMAIN_TYPE_PUBLIC); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageSubnet10) { + // Navigate to a private page on the 10.0.0.0/8 subnet and make requests to + // other 10.0.0.0/8 subnet resources. + const internal::PageAddressInfo& page = internal::kRouterRequest1; + NavigateToPageAndLoadResources(page, {{internal::kDiffSubnetRequest1, false}, + {internal::kDiffSubnetRequest3, false}, + {internal::kRouterRequest2, false}}); + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE); + + // The first two requests should be on the same subnet and the last request + // should be on a different subnet. + ExpectMetricsAndHistograms( + page, + { + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 10.0.10.200:80 + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_OTHER, + 0, 1}, // 10.15.20.25:12345 + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 192.168.10.1:443 + }, + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET) + .at(false), + 2}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET) + .at(false), + 1}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageSubnet172) { + // Navigate to a private page on the 10.0.0.0/8 subnet and make requests to + // other 10.0.0.0/8 subnet resources. + const internal::PageAddressInfo& page = internal::kDiffSubnetRequest2; + NavigateToPageAndLoadResources(page, {{internal::kDiffSubnetRequest4, false}, + {internal::kRouterRequest1, false}}); + ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE); + + // The first two requests should be on the same subnet and the last request + // should be on a different subnet. + ExpectMetricsAndHistograms( + page, + { + {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB, + 0, 1}, // 10.0.10.200:80 + {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_PRINT, + 0, 1}, // 172.31.100.20:515 + }, + { + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET) + .at(false), + 1}, + {internal::GetNonlocalhostHistogramNames() + .at(internal::DOMAIN_TYPE_PRIVATE) + .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET) + .at(false), + 1}, + }); +} + +TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageFailedLoad) { + GURL url(internal::kPrivatePage.url); + auto navigation_simulator = + content::NavigationSimulator::CreateRendererInitiated(url, main_rfh()); + navigation_simulator->Start(); + navigation_simulator->Fail(-20); + navigation_simulator->CommitErrorPage(); + + // Nothing should have been generated. + EXPECT_EQ(0ul, ukm_tester().sources_count()); + EXPECT_EQ(0ul, ukm_tester().entries_count()); + ExpectNoHistograms(); +}
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc index 87eb3d8..60f99b82 100644 --- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc +++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
@@ -15,6 +15,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/web_contents_tester.h" @@ -100,14 +101,22 @@ << "Main frame resources must have a GlobalRequestID."; } + // For consistency with browser-side navigation, we provide a null RFH for + // main frame and sub frame resources. + content::RenderFrameHost* render_frame_host_or_null = + (info.resource_type == content::RESOURCE_TYPE_MAIN_FRAME || + info.resource_type == content::RESOURCE_TYPE_SUB_FRAME) + ? nullptr + : web_contents()->GetMainFrame(); + observer_->OnRequestComplete( info.url, info.host_port_pair, info.frame_tree_node_id, request_id, - info.resource_type, info.was_cached, + render_frame_host_or_null, info.resource_type, info.was_cached, info.data_reduction_proxy_data ? info.data_reduction_proxy_data->DeepCopy() : nullptr, info.raw_body_bytes, info.original_network_content_length, - base::TimeTicks::Now(), 0); + base::TimeTicks::Now(), info.net_error); } void PageLoadMetricsObserverTestHarness::SimulateInputEvent(
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index 4d5a1ca1..c81c149 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -1023,6 +1023,27 @@ histogram_tester_.ExpectBucketCount(internal::kHistogramTotalBytes, 10, 1); } +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PayloadSizeChildFrame) { + ASSERT_TRUE(embedded_test_server()->Start()); + + auto waiter = CreatePageLoadMetricsWaiter(); + waiter->AddPageExpectation(TimingField::LOAD_EVENT); + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/page_load_metrics/large_iframe.html")); + waiter->Wait(); + + // Payload histograms are only logged when a page load terminates, so force + // navigation to another page. + NavigateToUntrackedUrl(); + + histogram_tester_.ExpectTotalCount(internal::kHistogramTotalBytes, 1); + + // Verify that there is a single sample recorded in the 10kB bucket (the size + // of the iframe response). + histogram_tester_.ExpectBucketCount(internal::kHistogramTotalBytes, 10, 1); +} + IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PayloadSizeIgnoresDownloads) { ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc index ce05d70..1c0c832 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/page_load_metrics/observers/google_captcha_observer.h" #include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.h" +#include "chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/lofi_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer.h" @@ -132,6 +133,8 @@ web_contents_); if (loading_predictor_observer) tracker->AddObserver(std::move(loading_predictor_observer)); + tracker->AddObserver( + base::MakeUnique<LocalNetworkRequestsPageLoadMetricsObserver>()); } else { std::unique_ptr<page_load_metrics::PageLoadMetricsObserver> prerender_observer =
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h index 122ccbc..3f964a2 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -255,7 +255,7 @@ // The network error encountered by the request, as defined by // net/base/net_error_list.h. If no error was encountered, this value will be // 0. - int net_error; + const int net_error; }; // Interface for PageLoadMetrics observers. All instances of this class are
diff --git a/chrome/browser/payments/android/journey_logger_android.cc b/chrome/browser/payments/android/journey_logger_android.cc index 8ee841e..6f3540b 100644 --- a/chrome/browser/payments/android/journey_logger_android.cc +++ b/chrome/browser/payments/android/journey_logger_android.cc
@@ -145,6 +145,12 @@ static_cast<JourneyLogger::NotShownReason>(jreason)); } +void JourneyLoggerAndroid::SetUserHadInitialFormOfPayment( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller) { + journey_logger_.SetUserHadInitialFormOfPayment(); +} + static jlong InitJourneyLoggerAndroid( JNIEnv* env, const JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/payments/android/journey_logger_android.h b/chrome/browser/payments/android/journey_logger_android.h index d6167d6..95afb75 100644 --- a/chrome/browser/payments/android/journey_logger_android.h +++ b/chrome/browser/payments/android/journey_logger_android.h
@@ -71,6 +71,9 @@ void SetNotShown(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller, jint jreason); + void SetUserHadInitialFormOfPayment( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller); private: JourneyLogger journey_logger_;
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tab_helper.cc b/chrome/browser/predictors/resource_prefetch_predictor_tab_helper.cc index 015a06d..e814cae5 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_tab_helper.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_tab_helper.cc
@@ -53,6 +53,7 @@ ResourcePrefetchPredictor::URLRequestSummary summary; summary.navigation_id = NavigationID(web_contents()); summary.resource_url = url; + summary.request_url = url; summary.mime_type = mime_type; summary.resource_type = ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index 913079e..5f75f2a 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -146,6 +146,7 @@ "cvox2/background/panel_command.js", "cvox2/background/panel_menu.js", "cvox2/background/panel_menu_item.js", + "cvox2/background/recovery_strategy.js", "cvox2/background/tabs_automation_handler.js", "cvox2/background/tree_walker.js", "cvox2/background/tutorial.js", @@ -679,6 +680,7 @@ "cvox2/background/live_regions_test.extjs", "cvox2/background/output_test.extjs", "cvox2/background/panel_test.extjs", + "cvox2/background/recovery_strategy_test.extjs", "cvox2/background/tree_walker_test.extjs", "host/chrome/tts_background_test.extjs", ]
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js index 1f3f614f..d544e6a 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
@@ -12,8 +12,10 @@ goog.provide('cursors.Range'); goog.provide('cursors.Unit'); +goog.require('AncestryRecoveryStrategy'); goog.require('AutomationPredicate'); goog.require('AutomationUtil'); +goog.require('RecoveryStrategy'); goog.require('StringUtil'); goog.require('constants'); @@ -84,7 +86,7 @@ // The exception is when a user types at the end of a line. In that case, // staying on the current node is appropriate. - if (node && node.nextOnLine && nextNode) { + if (node && node.nextOnLine && node.nextOnLine.role && nextNode) { node = nextNode; index = 0; } @@ -99,15 +101,8 @@ /** @type {number} @private */ this.index_ = index; - /** @type {Array<AutomationNode>} @private */ - this.ancestry_ = []; - var nodeWalker = node; - while (nodeWalker) { - this.ancestry_.push(nodeWalker); - nodeWalker = nodeWalker.parent; - if (nodeWalker && nodeWalker.role == RoleType.WINDOW) - break; - } + /** @type {RecoveryStrategy} */ + this.recovery_ = new AncestryRecoveryStrategy(node); }; /** @@ -177,16 +172,11 @@ * @return {AutomationNode} */ get node() { - for (var i = 0; i < this.ancestry_.length; i++) { - var firstValidNode = this.ancestry_[i]; - if (firstValidNode != null && firstValidNode.role !== undefined && - firstValidNode.root != undefined) { - return firstValidNode; - } - // If we have to walk up to an ancestor, reset the index to NODE_INDEX. + if (this.recovery_.requiresRecovery()) { + // If we need to recover, the index is no longer valid. this.index_ = cursors.NODE_INDEX; } - return null; + return this.recovery_.node; }, /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js index 99cbad3..7c8335d 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -13,6 +13,7 @@ goog.require('AutomationUtil'); goog.require('Output'); goog.require('Output.EventType'); +goog.require('TreePathRecoveryStrategy'); goog.require('cursors.Cursor'); goog.require('cursors.Range'); goog.require('cvox.BrailleBackground'); @@ -655,6 +656,8 @@ this.lineEndContainer_; /** @private {number} */ this.localLineEndContainerOffset_ = 0; + /** @type {RecoveryStrategy} */ + this.lineStartContainerRecovery_; this.computeLineData_(opt_baseLineOnStart); }; @@ -760,6 +763,11 @@ } this.localLineStartContainerOffset_ = textCountBeforeLineStart; + if (this.lineStartContainer_) { + this.lineStartContainerRecovery_ = + new TreePathRecoveryStrategy(this.lineStartContainer_); + } + finder = this.lineEnd_; while (finder.nextSibling) { finder = finder.nextSibling; @@ -902,7 +910,11 @@ this.localLineStartContainerOffset_) || (otherLine.lineEndContainer_ == this.lineEndContainer_ && otherLine.localLineEndContainerOffset_ == - this.localLineEndContainerOffset_); + this.localLineEndContainerOffset_) || + (otherLine.lineStartContainerRecovery_.node == + this.lineStartContainerRecovery_.node && + otherLine.localLineStartContainerOffset_ == + this.localLineStartContainerOffset_); }, /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js new file mode 100644 index 0000000..f3409ba --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js
@@ -0,0 +1,133 @@ +// 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. + +/** + * @fileoverview Defines various strategies for recovering automation nodes. + */ + +goog.provide('AncestryRecoveryStrategy'); +goog.provide('RecoveryStrategy'); +goog.provide('TreePathRecoveryStrategy'); + +goog.scope(function() { +var AutomationNode = chrome.automation.AutomationNode; +var RoleType = chrome.automation.RoleType; + +/** + * @param {!AutomationNode} node + * @constructor + */ +RecoveryStrategy = function(node) { + /** @private {!AutomationNode} */ + this.node_ = node; +}; + +RecoveryStrategy.prototype = { + /** @return {!AutomationNode} */ + get node() { + if (this.requiresRecovery()) + this.node_ = this.recover() || this.node_; + + return this.node_; + }, + + /** @return {boolean} */ + requiresRecovery: function() { + return !this.node_ || !this.node_.role; + }, + + /** + * @return {AutomationNode} + * @protected + */ + recover: function() { + return null; + } +}; + +/** + * A recovery strategy that uses the node's ancestors. + * @constructor + * @extends {RecoveryStrategy} + */ +AncestryRecoveryStrategy = function(node) { + RecoveryStrategy.call(this, node); + + /** @type {!Array<AutomationNode>} @private */ + this.ancestry_ = []; + var nodeWalker = node; + while (nodeWalker) { + this.ancestry_.push(nodeWalker); + nodeWalker = nodeWalker.parent; + if (nodeWalker && nodeWalker.role == RoleType.WINDOW) + break; + } +}; + +AncestryRecoveryStrategy.prototype = { + __proto__: RecoveryStrategy.prototype, + + /** @override */ + recover: function() { + return this.ancestry_[this.getFirstValidNodeIndex_()]; + }, + + /** + * @return {number} + * @protected + */ + getFirstValidNodeIndex_: function() { + for (var i = 0; i < this.ancestry_.length; i++) { + var firstValidNode = this.ancestry_[i]; + if (firstValidNode != null && firstValidNode.role !== undefined && + firstValidNode.root != undefined) { + return i; + } + } + return 0; + } +}; + +/** + * A recovery strategy that uses the node's tree path. + * @constructor + * @extends {AncestryRecoveryStrategy} + */ +TreePathRecoveryStrategy = function(node) { + AncestryRecoveryStrategy.call(this, node); + + /** @type {!Array<number>} @private */ + this.recoveryChildIndex_ = []; + var nodeWalker = node; + while (nodeWalker) { + this.recoveryChildIndex_.push(nodeWalker.indexInParent); + nodeWalker = nodeWalker.parent; + if (nodeWalker && nodeWalker.role == RoleType.WINDOW) + break; + } +}; + +TreePathRecoveryStrategy.prototype = { + __proto__: AncestryRecoveryStrategy.prototype, + + /** @override */ + recover: function() { + var index = this.getFirstValidNodeIndex_(); + if (index == 0) + return this.ancestry_[index]; + + // Otherwise, attempt to recover. + var node = this.ancestry_[index]; + for (var j = index - 1; j >= 0; j--) { + var childIndex = this.recoveryChildIndex_[j]; + var children = node.children; + if (!children[childIndex]) + return node; + node = children[childIndex]; + } + return node; + } +}; + +}); // goog.scope
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs new file mode 100644 index 0000000..41d70a1 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs
@@ -0,0 +1,71 @@ +// 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 test fixture. +GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js', + '../../testing/assert_additions.js']); + +/** + * Test fixture for recovery strategy tests. + * @constructor + * @extends {ChromeVoxNextE2ETest} + */ +function RecoveryStrategyTest() { + ChromeVoxNextE2ETest.call(this); + window.RoleType = chrome.automation.RoleType; +} + +RecoveryStrategyTest.prototype = { + __proto__: ChromeVoxNextE2ETest.prototype, +}; + +TEST_F('RecoveryStrategyTest', 'ReparentedRecovery', function() { + this.runWithLoadedTree(function() {/*! + <input type="text"></input> + <p id="p">hi</p> + <button id="go"</button> + <script> + document.getElementById('go').addEventListener('click', function() { + var p = document.getElementById('p'); + p.remove(); + document.body.appendChild(p); + }); + </script> + */}, function(root) { + var p = root.find({role: RoleType.PARAGRAPH}); + var s = root.find({role: RoleType.STATIC_TEXT}); + var b = root.find({role: RoleType.BUTTON}); + var bAncestryRecovery = new AncestryRecoveryStrategy(b); + var pAncestryRecovery = new AncestryRecoveryStrategy(p); + var sAncestryRecovery = new AncestryRecoveryStrategy(s); + var bTreePathRecovery = new TreePathRecoveryStrategy(b); + var pTreePathRecovery = new TreePathRecoveryStrategy(p); + var sTreePathRecovery = new TreePathRecoveryStrategy(s); + this.listenOnce(b, 'clicked', function() { + assertFalse(bAncestryRecovery.requiresRecovery()); + assertTrue(pAncestryRecovery.requiresRecovery()); + assertTrue(sAncestryRecovery.requiresRecovery()); + assertFalse(bTreePathRecovery.requiresRecovery()); + assertTrue(pTreePathRecovery.requiresRecovery()); + assertTrue(sTreePathRecovery.requiresRecovery()); + + assertEquals(RoleType.BUTTON, bAncestryRecovery.node.role); + assertEquals(root, pAncestryRecovery.node); + assertEquals(root, sAncestryRecovery.node); + + assertEquals(b, bTreePathRecovery.node); + assertEquals(b, pTreePathRecovery.node); + assertEquals(b, sTreePathRecovery.node); + + assertFalse(bAncestryRecovery.requiresRecovery()); + assertFalse(pAncestryRecovery.requiresRecovery()); + assertFalse(sAncestryRecovery.requiresRecovery()); + assertFalse(bTreePathRecovery.requiresRecovery()); + assertFalse(pTreePathRecovery.requiresRecovery()); + assertFalse(sTreePathRecovery.requiresRecovery()); + }); + // Trigger the change. + b.doDefault(); + }); +});
diff --git a/chrome/browser/resources/print_preview/previewarea/preview_area.js b/chrome/browser/resources/print_preview/previewarea/preview_area.js index 24b14be..0e2ff3c 100644 --- a/chrome/browser/resources/print_preview/previewarea/preview_area.js +++ b/chrome/browser/resources/print_preview/previewarea/preview_area.js
@@ -172,11 +172,6 @@ */ this.openSystemDialogButton_ = null; - /** - * If this is in a browser test (fake plugin). - * @private {boolean} - */ - this.isBrowserTest_ = false; } /** @@ -605,8 +600,6 @@ */ onDocumentReady_: function(event) { this.isDocumentReady_ = true; - if (this.isBrowserTest_) - this.isPluginReloaded_ = true; this.dispatchPreviewGenerationDoneIfReady_(); }, @@ -675,11 +668,6 @@ // being draggable. this.plugin_.style.pointerEvents = isDragging ? 'none' : 'auto'; }, - - /** @param {boolean} isTest Whether this instance is in a browser test. */ - setIsBrowserTest: function(isTest) { - this.isBrowserTest_ = isTest; - } }; // Export
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html index d8bee09..b9ab3dc5 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html +++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -19,8 +19,10 @@ } #show-files-button { - color: var(--google-blue-700); --paper-button-ink-color: white; + /* Left-align the text of the button with the rest of the card's text */ + -webkit-margin-start: calc(var(--settings-button-edge-spacing) * -1); + color: var(--google-blue-700); text-transform: inherit; } @@ -30,8 +32,8 @@ } .status-icon-container { + -webkit-padding-end: 12px; min-width: 28px; - padding-right: 12px; } .status-icon-remove { @@ -67,9 +69,22 @@ </div> <div id="details-container" class="settings-box two-line" hidden="[[!showDetails_]]"> - <div>[[detailsDescription]]</div> + <div> + $i18n{chromeCleanupExplanation} + <a href="$i18n{chromeCleanupLearnMoreUrl}" target="_blank"> + $i18n{learnMore} + </a> + </div> </div> - <div class="settings-box continuation" hidden="[[!showDetails_]]"> + <div class="settings-box continuation" hidden="[[!showLogsPermission_]]"> + <settings-toggle-button class="start" + id="chromeCleanupLogsUploadControl" + label="$i18n{chromeCleanupLogsUploadPermission}" + pref="[[logsUploadPref_]]" + on-settings-boolean-control-change="changeLogsPermission_"> + </settings-toggle-button> + </div> + <div class="settings-box" hidden="[[!showDetails_]]"> <div class="show-files-container start" hidden="[[showFilesToRemove_]]"> <paper-button id="show-files-button" on-tap="showFiles_"> $i18n{chromeCleanupLinkShowFiles}
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js index 89dd30b..25637213 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js +++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
@@ -66,9 +66,9 @@ }, /** @private */ - detailsDescription: { - type: String, - value: '', + showLogsPermission_: { + type: Boolean, + value: false, }, /** @private */ @@ -94,6 +94,14 @@ type: String, value: '', }, + + /** @private {chrome.settingsPrivate.PrefObject} */ + logsUploadPref_: { + type: Object, + value: function() { + return /** @type {chrome.settingsPrivate.PrefObject} */ ({}); + }, + }, }, /** @private {?settings.ChromeCleanupProxy} */ @@ -123,6 +131,9 @@ 'chrome-cleanup-on-reboot-required', this.onRebootRequired_.bind(this)); this.addWebUIListener( 'chrome-cleanup-on-dismiss', this.onDismiss_.bind(this)); + this.addWebUIListener( + 'chrome-cleanup-upload-permission-change', + this.onUploadPermissionChange_.bind(this)); this.browserProxy_.registerChromeCleanerObserver(); }, @@ -155,15 +166,13 @@ this.enableActionButton_( this.i18n('chromeCleanupDoneButtonLabel'), this.dismiss_.bind(this)); this.setIconDone_(); - } else if (idleReason == settings.ChromeCleanupIdleReason.CLEANING_FAILED) { + } else { + // Scanning-related idle reasons are unexpected. Show an error message for + // all reasons other than |CLEANING_SUCCEEDED|. this.title_ = this.i18n('chromeCleanupTitleErrorCantRemove'); this.enableActionButton_( this.i18n('chromeCleanupDoneButtonLabel'), this.dismiss_.bind(this)); this.setIconWarning_(); - } else { - // TODO(proberge): Handle other cases. - this.title_ = ''; - this.disableActionButton_(); } this.isRemoving_ = false; @@ -214,6 +223,7 @@ this.resetIcon_(); this.disableActionButton_(); this.enableDetails_(files); + this.showLogsPermission_ = false; }, /** @@ -242,6 +252,27 @@ }, /** + * @param {boolean} enabled Whether logs upload is enabled. + * @private + */ + onUploadPermissionChange_: function(enabled) { + this.logsUploadPref_ = { + key: '', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: enabled, + }; + }, + + /** + * @param {boolean} enabled Whether to enable logs upload. + * @private + */ + changeLogsPermission_: function(enabled) { + var enabled = this.$.chromeCleanupLogsUploadControl.checked; + this.browserProxy_.setLogsUploadPermission(enabled); + }, + + /** * Dismiss the card. * @private */ @@ -278,7 +309,7 @@ */ disableDetails_: function() { this.showDetails_ = false; - this.detailsDescription = ''; + this.showLogsPermission_ = false; this.showFilesToRemove_ = false; this.filesToRemove_ = []; }, @@ -290,7 +321,7 @@ */ enableDetails_: function(files) { this.showDetails_ = true; - this.detailsDescription = this.i18n('chromeCleanupExplanation'); + this.showLogsPermission_ = true; // Note: doesn't change the state of this.showFilesToRemove_. this.filesToRemove_ = files; }, @@ -300,7 +331,8 @@ * @private */ startCleanup_: function() { - this.browserProxy_.startCleanup(); + this.browserProxy_.startCleanup( + this.$.chromeCleanupLogsUploadControl.checked); }, /**
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js index b032a5cd..135379a 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js +++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
@@ -13,8 +13,9 @@ /** * Starts a cleanup on the user's computer. + * @param {boolean} logsUploadEnabled */ - startCleanup() {} + startCleanup(logsUploadEnabled) {} /** * Restarts the user's computer. @@ -25,6 +26,12 @@ * Hides the Cleanup page from the settings menu. */ dismissCleanupPage() {} + + /** + * Updates the cleanup logs upload permission status. + * @param {boolean} enabled + */ + setLogsUploadPermission(enabled) {} } /** @@ -37,8 +44,8 @@ } /** @override */ - startCleanup() { - chrome.send('startCleanup'); + startCleanup(logsUploadEnabled) { + chrome.send('startCleanup', [logsUploadEnabled]); } /** @override */ @@ -50,6 +57,11 @@ dismissCleanupPage() { chrome.send('dismissCleanupPage'); } + + /** @override */ + setLogsUploadPermission(enabled) { + chrome.send('setLogsUploadPermission', [enabled]); + } } cr.addSingletonGetter(ChromeCleanupProxyImpl);
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp b/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp index 1d6d6fc..d6c2e9b 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp
@@ -19,6 +19,7 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', + '<(EXTERNS_GYP):settings_private', 'chrome_cleanup_proxy', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index 1cc949ea..0591b4d2 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -376,25 +376,28 @@ } .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(--paper-yellow-500); + background-color: var(--search-bubble-color); border-radius: 2px; + max-width: 100px; + min-width: 64px; padding: 4px 10px; text-align: center; - width: 100px; } /* Provides the arrow which points at the anchor element. */ .search-bubble-innards::after { - background-color: var(--paper-yellow-500); + background-color: var(--search-bubble-color); content: ''; height: 10px; - left: 55px; + left: calc(50% - 5px); position: absolute; top: -5px; transform: rotate(-45deg);
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc index 021fac4..d42213e 100644 --- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -1409,7 +1409,7 @@ base::Unretained(this), run_loop.QuitClosure())); run_loop.Run(); ASSERT_TRUE(HasClientDownloadRequest()); - EXPECT_EQ(1, GetClientDownloadRequest()->archived_binary_size()); + EXPECT_EQ(2, GetClientDownloadRequest()->archived_binary_size()); EXPECT_TRUE(GetClientDownloadRequest()->has_download_type()); EXPECT_EQ(ClientDownloadRequest_DownloadType_ZIPPED_EXECUTABLE, GetClientDownloadRequest()->download_type());
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc index 346b630a..dcba4d2 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -1271,9 +1272,14 @@ referrer_chain.Get(3)); } +#if defined(OS_WIN) +#define MAYBE_SubFrameNewTabDownload DISABLED_SubFrameNewTabDownload +#else +#define MAYBE_SubFrameNewTabDownload SubFrameNewTabDownload +#endif // Click a link in a subframe and open download in a new tab. IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, - SubFrameNewTabDownload) { + MAYBE_SubFrameNewTabDownload) { GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL); ClickTestLink("sub_frame_download_attribution", 1, initial_url); std::string test_name =
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer_unittest.cc b/chrome/browser/safe_browsing/sandboxed_zip_analyzer_unittest.cc index 5bb3bff..4b434d8 100644 --- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer_unittest.cc +++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer_unittest.cc
@@ -216,7 +216,7 @@ ASSERT_TRUE(results.success); EXPECT_FALSE(results.has_executable); EXPECT_TRUE(results.has_archive); - EXPECT_EQ(0, results.archived_binary.size()); + EXPECT_EQ(1, results.archived_binary.size()); ASSERT_EQ(1u, results.archived_archive_filenames.size()); EXPECT_EQ(FILE_PATH_LITERAL("hello.zip"), results.archived_archive_filenames[0].value()); @@ -229,7 +229,7 @@ ASSERT_TRUE(results.success); EXPECT_FALSE(results.has_executable); EXPECT_TRUE(results.has_archive); - EXPECT_EQ(0, results.archived_binary.size()); + EXPECT_EQ(1, results.archived_binary.size()); ASSERT_EQ(1u, results.archived_archive_filenames.size()); EXPECT_EQ(FILE_PATH_LITERAL("hello.rar"), results.archived_archive_filenames[0].value()); @@ -242,7 +242,7 @@ ASSERT_TRUE(results.success); EXPECT_TRUE(results.has_executable); EXPECT_TRUE(results.has_archive); - ASSERT_EQ(1, results.archived_binary.size()); + ASSERT_EQ(2, results.archived_binary.size()); ExpectBinary(kSignedExe, results.archived_binary.Get(0)); ASSERT_EQ(1u, results.archived_archive_filenames.size()); EXPECT_EQ(FILE_PATH_LITERAL("hello.7z"), @@ -258,7 +258,7 @@ ASSERT_TRUE(results.success); EXPECT_TRUE(results.has_executable); EXPECT_TRUE(results.has_archive); - ASSERT_EQ(2, results.archived_binary.size()); + ASSERT_EQ(3, results.archived_binary.size()); BinaryData SignedExe = kSignedExe; SignedExe.file_basename = "signed.exe ";
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc index 8a7564c..d5f6929 100644 --- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -11,12 +11,44 @@ #include "components/sync/protocol/user_event_specifics.pb.h" #include "components/sync/user_events/user_event_service.h" +using base::Time; +using base::TimeDelta; using fake_server::FakeServer; using sync_pb::UserEventSpecifics; using sync_pb::SyncEntity; +using sync_pb::CommitResponse; namespace { +UserEventSpecifics CreateEvent(int minutes_ago) { + UserEventSpecifics specifics; + specifics.set_event_time_usec( + (Time::Now() - TimeDelta::FromMinutes(minutes_ago)).ToInternalValue()); + specifics.mutable_test_event(); + return specifics; +} + +CommitResponse::ResponseType BounceType( + CommitResponse::ResponseType type, + const fake_server::FakeServerEntity& entity) { + return type; +} + +CommitResponse::ResponseType TransientErrorFirst( + bool* first, + UserEventSpecifics* retry_specifics, + const fake_server::FakeServerEntity& entity) { + if (*first) { + *first = false; + SyncEntity sync_entity; + entity.SerializeAsProto(&sync_entity); + *retry_specifics = sync_entity.specifics().user_event(); + return CommitResponse::TRANSIENT_ERROR; + } else { + return CommitResponse::SUCCESS; + } +} + class UserEventEqualityChecker : public SingleClientStatusChangeChecker { public: UserEventEqualityChecker(browser_sync::ProfileSyncService* service, @@ -24,7 +56,8 @@ std::vector<UserEventSpecifics> expected_specifics) : SingleClientStatusChangeChecker(service), fake_server_(fake_server) { for (const UserEventSpecifics& specifics : expected_specifics) { - expected_specifics_[specifics.event_time_usec()] = specifics; + expected_specifics_.insert(std::pair<int64_t, UserEventSpecifics>( + specifics.event_time_usec(), specifics)); } } @@ -40,17 +73,24 @@ return false; } + // Because we have a multimap, we cannot just check counts and equality of + // items, but we need to make sure 2 of A and 1 of B is not the same as 1 of + // A and 2 of B. So to make this easy, copy the multimap and remove items. + std::multimap<int64_t, UserEventSpecifics> copied_expected_( + expected_specifics_.begin(), expected_specifics_.end()); for (const SyncEntity& entity : entities) { UserEventSpecifics server_specifics = entity.specifics().user_event(); - auto iter = expected_specifics_.find(server_specifics.event_time_usec()); + auto iter = copied_expected_.find(server_specifics.event_time_usec()); // We don't expect to encounter id matching events with different values, // this isn't going to recover so fail the test case now. - CHECK(expected_specifics_.end() != iter); + CHECK(copied_expected_.end() != iter); // TODO(skym): This may need to change if we start updating navigation_id // based on what sessions data is committed, and end up committing the // same event multiple times. EXPECT_EQ(iter->second.navigation_id(), server_specifics.navigation_id()); EXPECT_EQ(iter->second.event_case(), server_specifics.event_case()); + + copied_expected_.erase(iter); } return true; @@ -62,7 +102,7 @@ private: FakeServer* fake_server_; - std::map<int64_t, UserEventSpecifics> expected_specifics_; + std::multimap<int64_t, UserEventSpecifics> expected_specifics_; }; class SingleClientUserEventsSyncTest : public SyncTest { @@ -82,12 +122,67 @@ GetFakeServer()->GetSyncEntitiesByModelType(syncer::USER_EVENTS).size()); syncer::UserEventService* event_service = browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); - UserEventSpecifics specifics1; - specifics1.set_event_time_usec(base::Time::Now().ToInternalValue()); - specifics1.mutable_test_event(); + UserEventSpecifics specifics = CreateEvent(0); + event_service->RecordUserEvent(specifics); + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), {specifics}) + .Wait(); +} + +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, RetrySequential) { + ASSERT_TRUE(SetupSync()); + UserEventSpecifics specifics1 = CreateEvent(1); + UserEventSpecifics specifics2 = CreateEvent(2); + syncer::UserEventService* event_service = + browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); + + GetFakeServer()->OverrideResponseType( + base::Bind(&BounceType, CommitResponse::TRANSIENT_ERROR)); event_service->RecordUserEvent(specifics1); + + // This will block until we hit a TRANSIENT_ERROR, at which point we will + // regain control and can switch back to SUCCESS. UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), {specifics1}) .Wait(); + GetFakeServer()->OverrideResponseType( + base::Bind(&BounceType, CommitResponse::SUCCESS)); + // Because the fake server records commits even on failure, we are able to + // verify that the commit for this event reached the server twice. + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), + {specifics1, specifics1}) + .Wait(); + + // Only record |specifics2| after |specifics1| was successful to avoid race + // conditions. + event_service->RecordUserEvent(specifics2); + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), + {specifics1, specifics1, specifics2}) + .Wait(); +} + +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, RetryParallel) { + ASSERT_TRUE(SetupSync()); + bool first = true; + UserEventSpecifics specifics1 = CreateEvent(1); + UserEventSpecifics specifics2 = CreateEvent(2); + UserEventSpecifics retry_specifics; + + syncer::UserEventService* event_service = + browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); + + // We're not really sure if |specifics1| or |specifics2| is going to see the + // error, so record the one that does into |retry_specifics| and use it in + // expectations. + GetFakeServer()->OverrideResponseType( + base::Bind(&TransientErrorFirst, &first, &retry_specifics)); + + event_service->RecordUserEvent(specifics2); + event_service->RecordUserEvent(specifics1); + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), + {specifics1, specifics2}) + .Wait(); + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), + {specifics1, specifics2, retry_specifics}) + .Wait(); } } // namespace
diff --git a/chrome/browser/ui/autofill/popup_constants.h b/chrome/browser/ui/autofill/popup_constants.h index ca3a74a24..c2f6ed0 100644 --- a/chrome/browser/ui/autofill/popup_constants.h +++ b/chrome/browser/ui/autofill/popup_constants.h
@@ -5,10 +5,17 @@ #ifndef CHROME_BROWSER_UI_AUTOFILL_POPUP_CONSTANTS_H_ #define CHROME_BROWSER_UI_AUTOFILL_POPUP_CONSTANTS_H_ +#include "build/build_config.h" + namespace autofill { +#if defined(TOOLKIT_VIEWS) +// In views, the implementation takes care of the border itself. +const int kPopupBorderThickness = 0; +#else // TODO(crbug.com/676221): Change this to pixels const int kPopupBorderThickness = 1; +#endif } // namespace autofill
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index f04527b..44ab1e39 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -216,16 +216,9 @@ void ShowConflicts(Browser* browser) { #if defined(OS_WIN) - EnumerateModulesModel* model = EnumerateModulesModel::GetInstance(); - GURL conflict_url = model->GetConflictUrl(); - if (conflict_url.is_valid()) { - ShowSingletonTab(browser, conflict_url); - model->AcknowledgeConflictNotification(); - return; - } + EnumerateModulesModel::GetInstance()->AcknowledgeConflictNotification(); #endif - base::RecordAction(UserMetricsAction("AboutConflicts")); ShowSingletonTab(browser, GURL(kChromeUIConflictsURL)); }
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm index f6123f0b..c38ea78 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
@@ -248,8 +248,25 @@ void OmniboxViewMac::Update() { if (model()->UpdatePermanentText()) { + const bool was_select_all = IsSelectAll(); + NSTextView* text_view = + base::mac::ObjCCastStrict<NSTextView>([field_ currentEditor]); + const bool was_reversed = + [text_view selectionAffinity] == NSSelectionAffinityUpstream; + // Restore everything to the baseline look. RevertAll(); + + // Only select all when we have focus. If we don't have focus, selecting + // all is unnecessary since the selection will change on regaining focus, + // and can in fact cause artifacts, e.g. if the user is on the NTP and + // clicks a link to navigate, causing |was_select_all| to be vacuously true + // for the empty omnibox, and we then select all here, leading to the + // trailing portion of a long URL being scrolled into view. We could try + // and address cases like this, but it seems better to just not muck with + // things when the omnibox isn't focused to begin with. + if (was_select_all && model()->has_focus()) + SelectAll(was_reversed); } else { // TODO(shess): This corresponds to _win and _gtk, except those // guard it with a test for whether the security level changed.
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc index a3704890..454864c4 100644 --- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc +++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -866,18 +866,11 @@ // Check if RevertAll() resets the text and preserves the cursor position. omnibox_view->RevertAll(); - EXPECT_TRUE(omnibox_view->IsSelectAll()); + EXPECT_FALSE(omnibox_view->IsSelectAll()); EXPECT_EQ(old_text, omnibox_view->GetText()); omnibox_view->GetSelectionBounds(&start, &end); -#if defined(OS_MACOSX) - // Cocoa doesn't choose a direction until the user interacts with it, - // so it will have a default direction here. - std::swap(start, end); -#endif - // When |Revert()| calls |SelectAll()|, it requests a reverse selection - // so that the start of a long URL is in view. - EXPECT_EQ(11U, start); - EXPECT_EQ(0U, end); + EXPECT_EQ(3U, start); + EXPECT_EQ(3U, end); // Check that reverting clamps the cursor to the bounds of the new text. // Move the cursor to the end. @@ -893,11 +886,8 @@ omnibox_view->RevertAll(); // Cursor should be no further than original text. omnibox_view->GetSelectionBounds(&start, &end); -#if defined(OS_MACOSX) - std::swap(start, end); -#endif EXPECT_EQ(11U, start); - EXPECT_EQ(0U, end); + EXPECT_EQ(11U, end); } // Make sure the cursor position doesn't get set past the last character of @@ -1966,13 +1956,13 @@ test_toolbar_model->set_text(url_a); omnibox_view->Update(); EXPECT_EQ(url_a, omnibox_view->GetText()); - EXPECT_TRUE(omnibox_view->IsSelectAll()); + EXPECT_FALSE(omnibox_view->IsSelectAll()); // Test behavior of the "reversed" attribute of OmniboxView::SelectAll(). test_toolbar_model->set_text(ASCIIToUTF16("AB")); omnibox_view->Update(); // Should be at the end already. Shift+Left to select "reversed". - EXPECT_EQ(2u, GetSelectionSize(omnibox_view)); + EXPECT_EQ(0u, GetSelectionSize(omnibox_view)); ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, ui::EF_SHIFT_DOWN)); ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, ui::EF_SHIFT_DOWN)); EXPECT_EQ(2u, GetSelectionSize(omnibox_view)); @@ -1999,8 +1989,6 @@ omnibox_view->Update(); EXPECT_EQ(2u, GetSelectionSize(omnibox_view)); - // Force a forwards select-all because Cocoa will anyways. - omnibox_view->SelectAll(false); // Now Shift+Right should do nothing, and Shift+Left should reduce. // At the end, so Shift+Right should do nothing. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RIGHT, ui::EF_SHIFT_DOWN));
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index d5cd143..eab9341 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -340,6 +340,11 @@ delegate_->NeverSavePassword(); } +void ManagePasswordsBubbleModel::OnUsernameEdited(base::string16 new_username) { + DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); + pending_password_.username_value = std::move(new_username); +} + void ManagePasswordsBubbleModel::OnSaveClicked() { DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_SAVE);
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h index 0ff5bfa..03c9268 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h
@@ -46,6 +46,10 @@ // by the user. void OnNeverForThisSiteClicked(); + // Called by the view code when username is corrected using the edit button + // in PendingView. + void OnUsernameEdited(base::string16 new_username); + // Called by the view code when the save button is clicked by the user. void OnSaveClicked();
diff --git a/chrome/browser/ui/toolbar/app_menu_icon_controller.cc b/chrome/browser/ui/toolbar/app_menu_icon_controller.cc index 79b6acb..21b95c0 100644 --- a/chrome/browser/ui/toolbar/app_menu_icon_controller.cc +++ b/chrome/browser/ui/toolbar/app_menu_icon_controller.cc
@@ -12,8 +12,10 @@ #include "chrome/browser/upgrade_detector.h" #if defined(OS_WIN) +#include "base/feature_list.h" #include "base/win/windows_version.h" #include "chrome/browser/win/enumerate_modules_model.h" +#include "chrome/common/chrome_features.h" #endif namespace { @@ -57,7 +59,8 @@ // Returns true if we should show the warning for incompatible software. bool ShouldShowIncompatibilityWarning() { #if defined(OS_WIN) - return EnumerateModulesModel::GetInstance()->ShouldShowConflictWarning(); + return !base::FeatureList::IsEnabled(features::kModuleDatabase) && + EnumerateModulesModel::GetInstance()->ShouldShowConflictWarning(); #else return false; #endif @@ -77,9 +80,11 @@ UpgradeDetector::GetInstance()->AddObserver(this); #if defined(OS_WIN) - auto* modules = EnumerateModulesModel::GetInstance(); - modules->AddObserver(this); - modules->MaybePostScanningTask(); + if (!base::FeatureList::IsEnabled(features::kModuleDatabase)) { + auto* modules = EnumerateModulesModel::GetInstance(); + modules->AddObserver(this); + modules->MaybePostScanningTask(); + } #endif } @@ -87,7 +92,8 @@ UpgradeDetector::GetInstance()->RemoveObserver(this); #if defined(OS_WIN) - EnumerateModulesModel::GetInstance()->RemoveObserver(this); + if (!base::FeatureList::IsEnabled(features::kModuleDatabase)) + EnumerateModulesModel::GetInstance()->RemoveObserver(this); #endif }
diff --git a/chrome/browser/ui/toolbar/app_menu_icon_controller.h b/chrome/browser/ui/toolbar/app_menu_icon_controller.h index 2e7a98e5..cf3fe474 100644 --- a/chrome/browser/ui/toolbar/app_menu_icon_controller.h +++ b/chrome/browser/ui/toolbar/app_menu_icon_controller.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_TOOLBAR_APP_MENU_ICON_CONTROLLER_H_ #include "base/macros.h" +#include "build/build_config.h" #include "chrome/browser/upgrade_observer.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_observer.h" @@ -66,20 +67,20 @@ void UpdateDelegate(); private: +#if defined(OS_WIN) + // EnumerateModulesModel::Observer: + void OnScanCompleted() override; + void OnConflictsAcknowledged() override; +#endif + // content::NotificationObserver: void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; - // UpgradeObserver implementation. + // UpgradeObserver: void OnUpgradeRecommended() override; -#if defined(OS_WIN) - // EnumerateModulesModel: - void OnScanCompleted() override; - void OnConflictsAcknowledged() override; -#endif - Profile* profile_; Delegate* delegate_; content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc index 4540466..3c31853 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
@@ -9,14 +9,27 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" -#include "chrome/browser/ui/autofill/popup_constants.h" #include "ui/native_theme/native_theme.h" #include "ui/views/border.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/widget/widget.h" namespace autofill { +namespace { + +// The minimum vertical space between the bottom of the autofill popup and the +// bottom of the Chrome frame. +// TODO(crbug.com/739978): Investigate if we should compute this distance +// programmatically. 10dp may not be enough for windows with thick borders. +const int kPopupBottomMargin = 10; + +// The thickness of the border for the autofill popup in dp. +const int kPopupBorderThicknessDp = 1; + +} // namespace + AutofillPopupBaseView::AutofillPopupBaseView( AutofillPopupViewDelegate* delegate, views::Widget* parent_widget) @@ -55,14 +68,20 @@ params.parent = parent_widget_->GetNativeView(); widget->Init(params); + scroll_view_ = new views::ScrollView; + scroll_view_->set_hide_horizontal_scrollbar(true); + scroll_view_->SetContents(this); + + widget->SetContentsView(scroll_view_); + // No animation for popup appearance (too distracting). widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_HIDE); show_time_ = base::Time::Now(); } - SetBorder(views::CreateSolidBorder( - kPopupBorderThickness, + GetWidget()->GetRootView()->SetBorder(views::CreateSolidBorder( + kPopupBorderThicknessDp, GetNativeTheme()->GetSystemColor( ui::NativeTheme::kColorId_UnfocusedBorderColor))); @@ -105,7 +124,32 @@ } void AutofillPopupBaseView::DoUpdateBoundsAndRedrawPopup() { - GetWidget()->SetBounds(delegate_->popup_bounds()); + gfx::Rect bounds = delegate_->popup_bounds(); + + // |bounds| is in screen space and we want the bounds relative to the parent + // view. Since the parent is the scroll container, this will always be at + // position 0, 0 with dimensions specified by |bounds|. + SetSize(bounds.size()); + + // Compute the space available for the popup. It's the space between its top + // and the bottom of its parent view, minus some margin space. + int available_vertical_space = + parent_widget_->GetClientAreaBoundsInScreen().height() - + (bounds.y() - parent_widget_->GetClientAreaBoundsInScreen().y()) - + kPopupBottomMargin; + + if (available_vertical_space < bounds.height()) { + // The available space is not enough for the full popup so clamp the widget + // to what's available. Since the scroll view will show a scroll bar, + // increase the width so that the content isn't partially hidden. + bounds.set_width(bounds.width() + scroll_view_->GetScrollBarLayoutWidth()); + bounds.set_height(available_vertical_space); + } + + // Account for the scroll view's border so that the content has enough space. + bounds.set_height(bounds.height() + 2 * kPopupBorderThicknessDp); + bounds.set_width(bounds.width() + 2 * kPopupBorderThicknessDp); + GetWidget()->SetBounds(bounds); SchedulePaint(); }
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.h b/chrome/browser/ui/views/autofill/autofill_popup_base_view.h index 181b142..f407b96 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.h +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
@@ -78,6 +78,8 @@ // The widget of the window that triggered this popup. Weak reference. views::Widget* parent_widget_; + views::ScrollView* scroll_view_; + // The time when the popup was shown. base::Time show_time_;
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc index d23716a..94e9985b 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc
@@ -143,8 +143,10 @@ ShowView(); - gfx::Point display_point = - static_cast<views::View*>(view_)->GetBoundsInScreen().origin(); + gfx::Point display_point = static_cast<views::View*>(view_) + ->GetWidget() + ->GetClientAreaBoundsInScreen() + .origin(); gfx::Point expected_point = bounds.origin(); EXPECT_EQ(expected_point, display_point); }
diff --git a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc index 1deca5aa..a4ee391 100644 --- a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc +++ b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc
@@ -169,8 +169,7 @@ password_view_->Init(controller_->password(), controller_->SuggestedText(), font_list_); - password_view_->SetPosition(gfx::Point(kPopupBorderThickness, - kPopupBorderThickness)); + password_view_->SetPosition(gfx::Point()); password_view_->SizeToPreferredSize(); AddChildView(password_view_); } @@ -185,8 +184,7 @@ height += PasswordGenerationPopupController::kPopupPasswordSectionHeight + 1; } - return gfx::Size(width + 2 * kPopupBorderThickness, - height + 2 * kPopupBorderThickness); + return gfx::Size(width, height); } void PasswordGenerationPopupViewViews::Show() { @@ -220,25 +218,22 @@ void PasswordGenerationPopupViewViews::Layout() { // Need to leave room for the border. - int y = kPopupBorderThickness; - int popup_width = bounds().width() - 2 * kPopupBorderThickness; + int y = 0; + int popup_width = bounds().width(); if (controller_->display_password()) { // Currently the UI can change from not offering a password to offering // a password (e.g. the user is editing a generated password and deletes // it), but it can't change the other way around. CreatePasswordView(); password_view_->SetBounds( - kPopupBorderThickness, - y, - popup_width, + 0, 0, popup_width, PasswordGenerationPopupController::kPopupPasswordSectionHeight); divider_bounds_ = - gfx::Rect(kPopupBorderThickness, password_view_->bounds().bottom(), - popup_width, 1); + gfx::Rect(0, password_view_->bounds().bottom(), popup_width, 1); y = divider_bounds_.bottom(); } - help_label_->SetBounds(kPopupBorderThickness, y, popup_width, + help_label_->SetBounds(0, y, popup_width, help_label_->GetHeightForWidth(popup_width)); }
diff --git a/chrome/browser/ui/views/conflicting_module_view_win.cc b/chrome/browser/ui/views/conflicting_module_view_win.cc index 3b5d671..7fbd051 100644 --- a/chrome/browser/ui/views/conflicting_module_view_win.cc +++ b/chrome/browser/ui/views/conflicting_module_view_win.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" #include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" @@ -65,13 +66,6 @@ if (done_checking) return; // Only show the bubble once per launch. - auto* model = EnumerateModulesModel::GetInstance(); - GURL url = model->GetConflictUrl(); - if (!url.is_valid()) { - done_checking = true; - return; - } - // A pref that counts how often the Sideload Wipeout bubble has been shown. IntegerPrefMember bubble_shown; bubble_shown.Init(prefs::kModuleConflictBubbleShown, @@ -88,8 +82,8 @@ DCHECK(anchor_view); DCHECK(anchor_view->GetWidget()); - ConflictingModuleView* bubble_delegate = - new ConflictingModuleView(anchor_view, browser, url); + ConflictingModuleView* bubble_delegate = new ConflictingModuleView( + anchor_view, browser, GURL(chrome::kChromeUIConflictsURL)); views::BubbleDialogDelegateView::CreateBubble(bubble_delegate); bubble_delegate->ShowBubble();
diff --git a/chrome/browser/ui/views/conflicting_module_view_win.h b/chrome/browser/ui/views/conflicting_module_view_win.h index 5cb6b90..721188e1 100644 --- a/chrome/browser/ui/views/conflicting_module_view_win.h +++ b/chrome/browser/ui/views/conflicting_module_view_win.h
@@ -15,6 +15,7 @@ // This is the class that implements the UI for the bubble showing that there // is a 3rd party module loaded that conflicts with Chrome. +// TODO(pmonette): Delete this view when EnumerateModulesModel gets removed. class ConflictingModuleView : public views::BubbleDialogDelegateView, public EnumerateModulesModel::Observer { public:
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index f87cf715..b77191b 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -203,10 +203,31 @@ void OmniboxViewViews::Update() { const security_state::SecurityLevel old_security_level = security_level_; UpdateSecurityLevel(); - if (model()->UpdatePermanentText()) + if (model()->UpdatePermanentText()) { + // Select all the new text if the user had all the old text selected, or if + // there was no previous text (for new tab page URL replacement extensions). + // This makes one particular case better: the user clicks in the box to + // change it right before the permanent URL is changed. Since the new URL + // is still fully selected, the user's typing will replace the edit contents + // as they'd intended. + const bool was_select_all = IsSelectAll(); + const bool was_reversed = GetSelectedRange().is_reversed(); + RevertAll(); - else if (old_security_level != security_level_) + + // Only select all when we have focus. If we don't have focus, selecting + // all is unnecessary since the selection will change on regaining focus, + // and can in fact cause artifacts, e.g. if the user is on the NTP and + // clicks a link to navigate, causing |was_select_all| to be vacuously true + // for the empty omnibox, and we then select all here, leading to the + // trailing portion of a long URL being scrolled into view. We could try + // and address cases like this, but it seems better to just not muck with + // things when the omnibox isn't focused to begin with. + if (was_select_all && model()->has_focus()) + SelectAll(was_reversed); + } else if (old_security_level != security_level_) { EmphasizeURLComponents(); + } } base::string16 OmniboxViewViews::GetText() const {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc index 7435951..c1955e5c 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -286,7 +286,7 @@ // RevertAll after navigation to invalidate the selection range saved on blur. omnibox_view->RevertAll(); EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); - EXPECT_TRUE(omnibox_view->IsSelectAll()); + EXPECT_FALSE(omnibox_view->IsSelectAll()); // Pressing tab to focus the omnibox should select all text. while (!ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)) {
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc index 2ca04e95..902f85d1 100644 --- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc +++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -176,10 +176,6 @@ return l10n_util::GetStringUTF16(message_id); } -gfx::Size AccountChooserDialogView::CalculatePreferredSize() const { - return gfx::Size(kDesiredWidth, GetHeightForWidth(kDesiredWidth)); -} - void AccountChooserDialogView::StyledLabelLinkClicked(views::StyledLabel* label, const gfx::Range& range, int event_flags) {
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h index 0241a6b..63f2b0c 100644 --- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h +++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
@@ -43,9 +43,6 @@ int GetDialogButtons() const override; base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; - // views::View - gfx::Size CalculatePreferredSize() const override; - // StyledLabelListener: void StyledLabelLinkClicked(views::StyledLabel* label, const gfx::Range& range,
diff --git a/chrome/browser/ui/views/passwords/manage_password_items_view.cc b/chrome/browser/ui/views/passwords/manage_password_items_view.cc index 8d0661b7..cb6285d1 100644 --- a/chrome/browser/ui/views/passwords/manage_password_items_view.cc +++ b/chrome/browser/ui/views/passwords/manage_password_items_view.cc
@@ -217,24 +217,17 @@ void ManagePasswordItemsView::PasswordFormRow::AddCredentialsRow( views::GridLayout* layout) { ResetControls(); - int column_set_id = - host_->model_->state() == password_manager::ui::MANAGE_STATE - ? THREE_COLUMN_SET - : TWO_COLUMN_SET; - BuildColumnSetIfNeeded(layout, column_set_id); - layout->StartRow(0, column_set_id); + BuildColumnSetIfNeeded(layout, THREE_COLUMN_SET); + layout->StartRow(0, THREE_COLUMN_SET); layout->AddView(GenerateUsernameLabel(*password_form_).release(), 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, 0, fixed_height_); layout->AddView(GeneratePasswordLabel(*password_form_).release(), 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, 0, fixed_height_); - if (column_set_id == THREE_COLUMN_SET) { - delete_button_ = GenerateDeleteButton(this).release(); - layout->AddView(delete_button_, 1, 1, - views::GridLayout::TRAILING, views::GridLayout::FILL, - 0, fixed_height_); - } + delete_button_ = GenerateDeleteButton(this).release(); + layout->AddView(delete_button_, 1, 1, views::GridLayout::TRAILING, + views::GridLayout::FILL, 0, fixed_height_); } void ManagePasswordItemsView::PasswordFormRow::AddUndoRow( @@ -277,6 +270,7 @@ ManagePasswordsBubbleModel* manage_passwords_bubble_model, const std::vector<autofill::PasswordForm>* password_forms) : model_(manage_passwords_bubble_model) { + DCHECK_EQ(password_manager::ui::MANAGE_STATE, model_->state()); int fixed_height = PasswordFormRow::GetFixedHeight(model_->state()); for (const auto& password_form : *password_forms) { password_forms_rows_.push_back(base::MakeUnique<PasswordFormRow>( @@ -285,15 +279,6 @@ AddRows(); } -ManagePasswordItemsView::ManagePasswordItemsView( - ManagePasswordsBubbleModel* manage_passwords_bubble_model, - const autofill::PasswordForm* password_form) - : model_(manage_passwords_bubble_model) { - password_forms_rows_.push_back( - base::MakeUnique<PasswordFormRow>(this, password_form, 0)); - AddRows(); -} - ManagePasswordItemsView::~ManagePasswordItemsView() = default; void ManagePasswordItemsView::AddRows() { @@ -321,7 +306,6 @@ } void ManagePasswordItemsView::Refresh() { - DCHECK_NE(password_manager::ui::PENDING_PASSWORD_STATE, model_->state()); RemoveAllChildViews(true); AddRows(); }
diff --git a/chrome/browser/ui/views/passwords/manage_password_items_view.h b/chrome/browser/ui/views/passwords/manage_password_items_view.h index 3cecaf3..85662b4 100644 --- a/chrome/browser/ui/views/passwords/manage_password_items_view.h +++ b/chrome/browser/ui/views/passwords/manage_password_items_view.h
@@ -28,18 +28,12 @@ const autofill::PasswordForm& form); // A custom view of individual credentials. The view is represented as a table -// where each row can be in three distinct states: -// -// * Present already-saved credentials to the user for management. -// * Offer the user the ability to undo a deletion action. +// where each row can offer the user the ability to undo a deletion action. class ManagePasswordItemsView : public views::View { public: ManagePasswordItemsView( ManagePasswordsBubbleModel* manage_passwords_bubble_model, const std::vector<autofill::PasswordForm>* password_forms); - ManagePasswordItemsView( - ManagePasswordsBubbleModel* manage_passwords_bubble_model, - const autofill::PasswordForm* password_form); private: class PasswordFormRow;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc index 89cc567..9de3a026 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -300,7 +300,7 @@ // views::View: bool OnKeyPressed(const ui::KeyEvent& event) override; - void ToggleEditingState(); + void ToggleEditingState(bool accept_changes); ManagePasswordsBubbleView* parent_; @@ -393,7 +393,7 @@ const ui::Event& event) { // TODO(https://crbug.com/734965): Implement edit button logic. if (sender == edit_button_) { - ToggleEditingState(); + ToggleEditingState(false); return; } if (sender == save_button_) { @@ -421,7 +421,7 @@ View* focused_before, View* focused_now) { if (editing_ && focused_before == username_field_) { - ToggleEditingState(); + ToggleEditingState(true); } } @@ -429,13 +429,18 @@ const ui::KeyEvent& event) { if (editing_ && (event.key_code() == ui::KeyboardCode::VKEY_RETURN || event.key_code() == ui::KeyboardCode::VKEY_ESCAPE)) { - ToggleEditingState(); + ToggleEditingState(event.key_code() == ui::KeyboardCode::VKEY_RETURN); return true; } return false; } -void ManagePasswordsBubbleView::PendingView::ToggleEditingState() { +void ManagePasswordsBubbleView::PendingView::ToggleEditingState( + bool accept_changes) { + if (editing_ && accept_changes) { + parent_->model()->OnUsernameEdited( + static_cast<views::Textfield*>(username_field_)->text()); + } editing_ = !editing_; edit_button_->SetEnabled(!editing_); RemoveChildView(username_field_); @@ -719,31 +724,29 @@ layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); SetLayoutManager(layout); - // Create the pending credential item, update button. - View* item = nullptr; - if (parent->model()->ShouldShowMultipleAccountUpdateUI()) { - selection_view_ = new CredentialsSelectionView(parent->model()); - item = selection_view_; - } else { - item = new ManagePasswordItemsView(parent_->model(), - &parent->model()->pending_password()); - } - nope_button_ = views::MdTextButton::CreateSecondaryUiButton( - this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_BUTTON)); - - update_button_ = views::MdTextButton::CreateSecondaryUiBlueButton( - this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UPDATE_BUTTON)); - - BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); - // Credential row. - layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); - layout->AddView(item); + if (parent->model()->ShouldShowMultipleAccountUpdateUI()) { + BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); + layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); + layout->AddView(new CredentialsSelectionView(parent->model())); + } else { + BuildColumnSet(layout, DOUBLE_VIEW_COLUMN_SET); + layout->StartRow(0, DOUBLE_VIEW_COLUMN_SET); + const autofill::PasswordForm* password_form = + &parent_->model()->pending_password(); + layout->AddView(GenerateUsernameLabel(*password_form).release()); + layout->AddView(GeneratePasswordLabel(*password_form).release()); + } layout->AddPaddingRow( 0, layout_provider->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS).bottom()); // Button row. + nope_button_ = views::MdTextButton::CreateSecondaryUiButton( + this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_BUTTON)); + + update_button_ = views::MdTextButton::CreateSecondaryUiBlueButton( + this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UPDATE_BUTTON)); BuildColumnSet(layout, DOUBLE_BUTTON_COLUMN_SET); layout->StartRowWithPadding( 0, DOUBLE_BUTTON_COLUMN_SET, 0,
diff --git a/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc b/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc index ac7d985..73c7068d 100644 --- a/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/profiles/profile.h" @@ -446,19 +447,40 @@ std::vector<std::unique_ptr<autofill::PasswordForm>> local_credentials; autofill::PasswordForm form; form.origin = origin; - form.display_name = base::ASCIIToUTF16("Peter"); + form.display_name = base::ASCIIToUTF16("Peter Pan"); form.username_value = base::ASCIIToUTF16("peter@pan.test"); if (name == "PopupAutoSigninPrompt") { form.icon_url = GURL("broken url"); local_credentials.push_back(base::MakeUnique<autofill::PasswordForm>(form)); form.icon_url = GURL("https://google.com/icon.png"); - form.display_name = base::ASCIIToUTF16("Peter Pan"); + form.display_name = base::ASCIIToUTF16("Peter"); form.federation_origin = url::Origin(GURL("https://google.com/federation")); local_credentials.push_back(base::MakeUnique<autofill::PasswordForm>(form)); SetupChooseCredentials(std::move(local_credentials), origin); ASSERT_TRUE(controller()->current_account_chooser()); - } else if (name == "PopupAccountChooserWithSingleCredentialClickSignIn") { + } else if (base::StartsWith(name, "PopupAccountChooserWith", + base::CompareCase::SENSITIVE)) { local_credentials.push_back(base::MakeUnique<autofill::PasswordForm>(form)); + if (name == "PopupAccountChooserWithMultipleCredentialClickSignIn") { + form.icon_url = GURL("https://google.com/icon.png"); + form.display_name = base::ASCIIToUTF16("Tinkerbell"); + form.username_value = base::ASCIIToUTF16("tinkerbell@pan.test"); + form.federation_origin = + url::Origin(GURL("https://google.com/neverland")); + local_credentials.push_back( + base::MakeUnique<autofill::PasswordForm>(form)); + form.display_name = base::ASCIIToUTF16("James Hook"); + form.username_value = base::ASCIIToUTF16("james@pan.test"); + form.federation_origin = + url::Origin(GURL("https://google.com/jollyroger")); + local_credentials.push_back( + base::MakeUnique<autofill::PasswordForm>(form)); + form.display_name = base::ASCIIToUTF16("Wendy Darling"); + form.username_value = base::ASCIIToUTF16("wendy@pan.test"); + form.federation_origin = url::Origin(GURL("https://google.com/london")); + local_credentials.push_back( + base::MakeUnique<autofill::PasswordForm>(form)); + } SetupChooseCredentials(std::move(local_credentials), origin); } else { ADD_FAILURE() << "Unknown dialog type"; @@ -477,6 +499,12 @@ RunDialog(); } +IN_PROC_BROWSER_TEST_F( + PasswordDialogViewTest, + InvokeDialog_PopupAccountChooserWithMultipleCredentialClickSignIn) { + RunDialog(); +} + IN_PROC_BROWSER_TEST_F(PasswordDialogViewTest, InvokeDialog_AutoSigninFirstRun) { RunDialog();
diff --git a/chrome/browser/ui/views/payments/modifiers_browsertest.cc b/chrome/browser/ui/views/payments/modifiers_browsertest.cc new file mode 100644 index 0000000..5482872 --- /dev/null +++ b/chrome/browser/ui/views/payments/modifiers_browsertest.cc
@@ -0,0 +1,239 @@ +// 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 <vector> + +#include "base/macros.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h" +#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/web_modal/web_contents_modal_dialog_manager.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" + +namespace payments { + +class PaymentRequestModifiersTest : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestModifiersTest() + : PaymentRequestBrowserTestBase( + "/payment_request_bobpay_and_basic_card_with_basic_card_modifiers_" + "test.html") {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + PaymentRequestBrowserTestBase::SetUpCommandLine(command_line); + command_line->AppendSwitch( + switches::kEnableExperimentalWebPlatformFeatures); + } + + private: + DISALLOW_COPY_AND_ASSIGN(PaymentRequestModifiersTest); +}; + +IN_PROC_BROWSER_TEST_F(PaymentRequestModifiersTest, + NoModifierAppliedIfNoSelectedInstrument) { + InvokePaymentRequestUI(); + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$5.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // There's only the total line. + EXPECT_EQ(1, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +IN_PROC_BROWSER_TEST_F( + PaymentRequestModifiersTest, + ModifierAppliedIfApplicableSelectedInstrumentWithoutTypeOrNetwork) { + autofill::AutofillProfile profile(autofill::test::GetFullProfile()); + AddAutofillProfile(profile); + autofill::CreditCard card( + autofill::test::GetMaskedServerCard()); // Mastercard card. + card.set_billing_address_id(profile.guid()); + card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); + AddCreditCard(card); + + InvokePaymentRequestUI(); + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$4.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // A line for the discount and one for the total. + EXPECT_EQ(2, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +IN_PROC_BROWSER_TEST_F( + PaymentRequestModifiersTest, + ModifierAppliedIfApplicableSelectedInstrumentWithCreditSupportedType) { + autofill::AutofillProfile profile(autofill::test::GetFullProfile()); + AddAutofillProfile(profile); + autofill::CreditCard card( + autofill::test::GetMaskedServerCard()); // Mastercard card. + card.set_billing_address_id(profile.guid()); + card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); + AddCreditCard(card); + + ResetEventObserver(DialogEvent::DIALOG_OPENED); + content::WebContents* web_contents = GetActiveWebContents(); + const std::string click_buy_button_js = + "(function() { " + "document.getElementById('credit_supported_type')." + "click(); })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, click_buy_button_js)); + WaitForObservedEvent(); + // The web-modal dialog should be open. + web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager = + web_modal::WebContentsModalDialogManager::FromWebContents(web_contents); + EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); + + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$4.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // A line for the discount and one for the total. + EXPECT_EQ(2, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +IN_PROC_BROWSER_TEST_F( + PaymentRequestModifiersTest, + ModifierNotAppliedIfSelectedInstrumentWithDebitSupportedType) { + autofill::AutofillProfile profile(autofill::test::GetFullProfile()); + AddAutofillProfile(profile); + autofill::CreditCard card( + autofill::test::GetMaskedServerCard()); // Mastercard card. + card.set_billing_address_id(profile.guid()); + card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); + AddCreditCard(card); + + ResetEventObserver(DialogEvent::DIALOG_OPENED); + content::WebContents* web_contents = GetActiveWebContents(); + const std::string click_buy_button_js = + "(function() { " + "document.getElementById('debit_supported_type').click(" + "); })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, click_buy_button_js)); + WaitForObservedEvent(); + // The web-modal dialog should be open. + web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager = + web_modal::WebContentsModalDialogManager::FromWebContents(web_contents); + EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); + + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$5.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // There's only the total line. + EXPECT_EQ(1, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +IN_PROC_BROWSER_TEST_F( + PaymentRequestModifiersTest, + ModifierAppliedIfApplicableSelectedInstrumentWithMatchingNetwork) { + autofill::AutofillProfile profile(autofill::test::GetFullProfile()); + AddAutofillProfile(profile); + autofill::CreditCard card( + autofill::test::GetMaskedServerCard()); // Mastercard card. + card.set_billing_address_id(profile.guid()); + card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); + AddCreditCard(card); + + ResetEventObserver(DialogEvent::DIALOG_OPENED); + content::WebContents* web_contents = GetActiveWebContents(); + const std::string click_buy_button_js = + "(function() { " + "document.getElementById('mastercard_supported_network'" + ").click(); })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, click_buy_button_js)); + WaitForObservedEvent(); + // The web-modal dialog should be open. + web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager = + web_modal::WebContentsModalDialogManager::FromWebContents(web_contents); + EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); + + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$4.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // A line for the discount and one for the total. + EXPECT_EQ(2, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +IN_PROC_BROWSER_TEST_F( + PaymentRequestModifiersTest, + ModifierNotAppliedIfSelectedInstrumentWithoutMatchingNetwork) { + autofill::AutofillProfile profile(autofill::test::GetFullProfile()); + AddAutofillProfile(profile); + autofill::CreditCard card( + autofill::test::GetMaskedServerCard()); // Mastercard card. + card.set_billing_address_id(profile.guid()); + card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); + AddCreditCard(card); + + ResetEventObserver(DialogEvent::DIALOG_OPENED); + content::WebContents* web_contents = GetActiveWebContents(); + const std::string click_buy_button_js = + "(function() { " + "document.getElementById('visa_supported_network')." + "click(); })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, click_buy_button_js)); + WaitForObservedEvent(); + // The web-modal dialog should be open. + web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager = + web_modal::WebContentsModalDialogManager::FromWebContents(web_contents); + EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); + + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$5.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // There's only the total line. + EXPECT_EQ(1, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestModifiersTest, + ModifierNotAppliedToUnknownType) { + autofill::AutofillProfile profile(autofill::test::GetFullProfile()); + AddAutofillProfile(profile); + autofill::CreditCard card(autofill::test::GetCreditCard()); // Visa card. + card.set_billing_address_id(profile.guid()); + AddCreditCard(card); + + InvokePaymentRequestUI(); + OpenOrderSummaryScreen(); + + EXPECT_EQ(base::ASCIIToUTF16("$5.00"), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + // There's only the total line. + EXPECT_EQ(1, dialog_view() + ->view_stack_for_testing() + ->top() + ->GetViewByID(static_cast<int>(DialogViewID::CONTENT_VIEW)) + ->child_count()); +} + +} // namespace payments
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.cc b/chrome/browser/ui/views/payments/order_summary_view_controller.cc index 890788af..0c16806 100644 --- a/chrome/browser/ui/views/payments/order_summary_view_controller.cc +++ b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
@@ -170,35 +170,40 @@ DialogViewID::ORDER_SUMMARY_LINE_ITEM_1, DialogViewID::ORDER_SUMMARY_LINE_ITEM_2, DialogViewID::ORDER_SUMMARY_LINE_ITEM_3}; - for (size_t i = 0; i < spec()->details().display_items.size(); i++) { + const auto& display_items = + spec()->GetDisplayItems(state()->selected_instrument()); + for (size_t i = 0; i < display_items.size(); i++) { DialogViewID view_id = i < line_items.size() ? line_items[i] : DialogViewID::VIEW_ID_NONE; base::string16 currency = base::UTF8ToUTF16(""); if (is_mixed_currency) { - currency = base::UTF8ToUTF16( - spec()->details().display_items[i]->amount->currency); + currency = base::UTF8ToUTF16((*display_items[i])->amount->currency); } content_view->AddChildView( CreateLineItemView( - base::UTF8ToUTF16(spec()->details().display_items[i]->label), - currency, - spec()->GetFormattedCurrencyAmount( - spec()->details().display_items[i]->amount), + base::UTF8ToUTF16((*display_items[i])->label), currency, + spec()->GetFormattedCurrencyAmount((*display_items[i])->amount), false, DialogViewID::VIEW_ID_NONE, view_id) .release()); } base::string16 total_label_value = l10n_util::GetStringFUTF16( IDS_PAYMENT_REQUEST_ORDER_SUMMARY_SHEET_TOTAL_FORMAT, - base::UTF8ToUTF16(spec()->details().total->amount->currency), - spec()->GetFormattedCurrencyAmount(spec()->details().total->amount)); + base::UTF8ToUTF16( + spec()->GetTotal(state()->selected_instrument())->amount->currency), + spec()->GetFormattedCurrencyAmount( + spec()->GetTotal(state()->selected_instrument())->amount)); content_view->AddChildView( CreateLineItemView( - base::UTF8ToUTF16(spec()->details().total->label), - base::UTF8ToUTF16(spec()->details().total->amount->currency), - spec()->GetFormattedCurrencyAmount(spec()->details().total->amount), + base::UTF8ToUTF16( + spec()->GetTotal(state()->selected_instrument())->label), + base::UTF8ToUTF16(spec() + ->GetTotal(state()->selected_instrument()) + ->amount->currency), + spec()->GetFormattedCurrencyAmount( + spec()->GetTotal(state()->selected_instrument())->amount), true, DialogViewID::ORDER_SUMMARY_TOTAL_CURRENCY_LABEL, DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL) .release());
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h b/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h index cea42989..e0211d8f7 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h
@@ -14,6 +14,7 @@ enum class DialogViewID : int { VIEW_ID_NONE = autofill::MAX_VALID_FIELD_TYPE, + CONTENT_VIEW, // The main content view filled by each sheet // The following are views::Button (clickable). PAYMENT_SHEET_CONTACT_INFO_SECTION,
diff --git a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc index ff960d9f..b7fdae6 100644 --- a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc
@@ -434,8 +434,8 @@ NavigateTo("/payment_request_email_test.html"); // Initiated should be logged. - histogram_tester.ExpectBucketCount("PaymentRequest.CheckoutFunnel.Initiated", - 1, 1); + histogram_tester.ExpectUniqueSample("PaymentRequest.CheckoutFunnel.Initiated", + 1, 1); // Show should not be logged. histogram_tester.ExpectTotalCount("PaymentRequest.CheckoutFunnel.Shown", 0); // Abort should not be logged. @@ -455,6 +455,91 @@ "PaymentRequest.UserHadSuggestionsForEverything", 0); histogram_tester.ExpectTotalCount( "PaymentRequest.UserDidNotHaveSuggestionsForEverything", 0); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserHadInitialFormOfPayment", 0); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment", 0); +} + +class PaymentRequestInitialFormOfPaymentTest + : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestInitialFormOfPaymentTest() + : PaymentRequestBrowserTestBase("/payment_request_email_test.html") {} + + private: + DISALLOW_COPY_AND_ASSIGN(PaymentRequestInitialFormOfPaymentTest); +}; + +IN_PROC_BROWSER_TEST_F(PaymentRequestInitialFormOfPaymentTest, + UserHadInitialFormOfPayment) { + base::HistogramTester histogram_tester; + + // Add an address and a credit card on file. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Show a Payment Request. + InvokePaymentRequestUI(); + + // Navigate away to abort the Payment Request and trigger the logs. + NavigateTo("/payment_request_email_test.html"); + + // The fact that the user had a form of payment on file should be recorded. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", + JourneyLogger::COMPLETION_STATUS_USER_ABORTED, 1); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + 0); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestInitialFormOfPaymentTest, + UserDidNotHaveInitialFormOfPayment_NoCard) { + base::HistogramTester histogram_tester; + + // Show a Payment Request. The user has no form of payment on file. + InvokePaymentRequestUI(); + + // Navigate away to abort the Payment Request and trigger the logs. + NavigateTo("/payment_request_email_test.html"); + + // The fact that the user had no form of payment on file should be recorded. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + JourneyLogger::COMPLETION_STATUS_USER_ABORTED, 1); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", 0); +} + +IN_PROC_BROWSER_TEST_F( + PaymentRequestInitialFormOfPaymentTest, + UserDidNotHaveInitialFormOfPayment_CardNetworkNotSupported) { + base::HistogramTester histogram_tester; + + // Add an address and an AMEX credit card on file. AMEX is not supported by + // the merchant. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard2(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // AMEX. + + // Show a Payment Request. + InvokePaymentRequestUI(); + + // Navigate away to abort the Payment Request and trigger the logs. + NavigateTo("/payment_request_email_test.html"); + + // The fact that the user had no form of payment on file should be recorded. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + JourneyLogger::COMPLETION_STATUS_USER_ABORTED, 1); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", 0); } } // namespace payments
diff --git a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc index 17c4ceb..07436a9 100644 --- a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc +++ b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
@@ -250,6 +250,7 @@ content_view_->SetPaintToLayer(); content_view_->layer()->SetFillsBoundsOpaquely(true); content_view_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE)); + content_view_->set_id(static_cast<int>(DialogViewID::CONTENT_VIEW)); pane_layout->AddView(content_view_); pane_->SizeToPreferredSize();
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc index a9c1cf5..8e759e6b 100644 --- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -555,8 +555,8 @@ views::GridLayout::FIXED, kItemSummaryPriceFixedWidth, kItemSummaryPriceFixedWidth); - const std::vector<mojom::PaymentItemPtr>& items = - spec()->details().display_items; + const std::vector<const mojom::PaymentItemPtr*>& items = + spec()->GetDisplayItems(state()->selected_instrument()); bool is_mixed_currency = spec()->IsMixedCurrency(); // The inline items section contains the first 2 display items of the @@ -572,7 +572,7 @@ for (size_t i = 0; i < items.size() && i < displayed_items; ++i) { layout->StartRow(0, 0); std::unique_ptr<views::Label> summary = - base::MakeUnique<views::Label>(base::UTF8ToUTF16(items[i]->label)); + base::MakeUnique<views::Label>(base::UTF8ToUTF16((*items[i])->label)); summary->SetHorizontalAlignment(gfx::ALIGN_LEFT); layout->AddView(summary.release()); @@ -580,9 +580,10 @@ CreateInlineCurrencyAmountItem( is_mixed_currency ? base::UTF8ToUTF16( - spec()->GetFormattedCurrencyCode(items[i]->amount)) + spec()->GetFormattedCurrencyCode((*items[i])->amount)) : base::string16(), - spec()->GetFormattedCurrencyAmount(items[i]->amount), true, false) + spec()->GetFormattedCurrencyAmount((*items[i])->amount), true, + false) .release()); } @@ -603,14 +604,17 @@ layout->StartRow(0, 0); layout->AddView( - CreateBoldLabel(base::UTF8ToUTF16(spec()->details().total->label)) + CreateBoldLabel( + base::UTF8ToUTF16( + spec()->GetTotal(state()->selected_instrument())->label)) .release()); layout->AddView( CreateInlineCurrencyAmountItem( base::UTF8ToUTF16(spec()->GetFormattedCurrencyCode( - spec()->details().total->amount)), - spec()->GetFormattedCurrencyAmount(spec()->details().total->amount), + spec()->GetTotal(state()->selected_instrument())->amount)), + spec()->GetFormattedCurrencyAmount( + spec()->GetTotal(state()->selected_instrument())->amount), false, true) .release()); @@ -849,7 +853,7 @@ builder.Tag(PaymentSheetViewControllerTags::SHOW_SHIPPING_OPTION_BUTTON); if (state()->selected_shipping_profile()) { - if (spec()->details().shipping_options.empty()) { + if (spec()->GetShippingOptions().empty()) { // 1.1 No shipping options, do not display the row. return nullptr; } @@ -868,16 +872,16 @@ } else { // 1.3 There are options, none are selected: show the enabled Choose // button. + const auto& shipping_options = spec()->GetShippingOptions(); return builder .Id(DialogViewID::PAYMENT_SHEET_SHIPPING_OPTION_SECTION_BUTTON) - .CreateWithButton( - base::UTF8ToUTF16(spec()->details().shipping_options[0]->label), - l10n_util::GetPluralStringFUTF16( - IDS_PAYMENT_REQUEST_SHIPPING_OPTIONS_PREVIEW, - spec()->details().shipping_options.size() - 1), - spec()->details().shipping_options.size() - 1, - l10n_util::GetStringUTF16(IDS_CHOOSE), - /*button_enabled=*/true); + .CreateWithButton(base::UTF8ToUTF16(shipping_options[0]->label), + l10n_util::GetPluralStringFUTF16( + IDS_PAYMENT_REQUEST_SHIPPING_OPTIONS_PREVIEW, + shipping_options.size() - 1), + shipping_options.size() - 1, + l10n_util::GetStringUTF16(IDS_CHOOSE), + /*button_enabled=*/true); } } else { // 2. There is no selected address: do not show the shipping option section.
diff --git a/chrome/browser/ui/views/payments/profile_list_view_controller.cc b/chrome/browser/ui/views/payments/profile_list_view_controller.cc index dcd0b80..1da06e3 100644 --- a/chrome/browser/ui/views/payments/profile_list_view_controller.cc +++ b/chrome/browser/ui/views/payments/profile_list_view_controller.cc
@@ -172,7 +172,7 @@ // | Warning icon | Warning message | // --------------------------------------------- std::unique_ptr<views::View> CreateHeaderView() override { - if (!spec()->details().shipping_options.empty()) + if (!spec()->GetShippingOptions().empty()) return nullptr; auto header_view = base::MakeUnique<views::View>();
diff --git a/chrome/browser/ui/views/payments/shipping_option_view_controller.cc b/chrome/browser/ui/views/payments/shipping_option_view_controller.cc index 79385cc..d8ed2739 100644 --- a/chrome/browser/ui/views/payments/shipping_option_view_controller.cc +++ b/chrome/browser/ui/views/payments/shipping_option_view_controller.cc
@@ -80,7 +80,7 @@ PaymentRequestDialogView* dialog) : PaymentRequestSheetController(spec, state, dialog) { spec->AddObserver(this); - for (const auto& option : spec->details().shipping_options) { + for (const auto& option : spec->GetShippingOptions()) { shipping_option_list_.AddItem(base::MakeUnique<ShippingOptionItem>( option.get(), spec, state, &shipping_option_list_, dialog, option.get() == spec->selected_shipping_option()));
diff --git a/chrome/browser/ui/views/payments/view_stack.h b/chrome/browser/ui/views/payments/view_stack.h index 0472c6c..9b51d1b1 100644 --- a/chrome/browser/ui/views/payments/view_stack.h +++ b/chrome/browser/ui/views/payments/view_stack.h
@@ -48,6 +48,9 @@ void Layout() override; void RequestFocus() override; + // Returns the top state of the stack. + views::View* top() { return stack_.back().get(); } + private: FRIEND_TEST_ALL_PREFIXES( ViewStackTest, TestPopStateRemovesChildViewAndCleansUpState); @@ -58,9 +61,6 @@ friend class ViewStackTest; friend class payments::PaymentRequestBrowserTestBase; - // Returns the top state of the stack, used in tests. - views::View* top() { return stack_.back().get(); } - // Marks all views, except the topmost, as invisible. void HideCoveredViews();
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc index c15ebea..7118b9f 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -4,13 +4,17 @@ #include "chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h" +#include <stdint.h> + #include "ash/display/window_tree_host_manager.h" #include "ash/shell.h" +#include "base/stl_util.h" #include "content/public/browser/browser_thread.h" #include "ui/display/display.h" -#include "ui/display/display_layout.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" +#include "ui/events/devices/device_data_manager.h" +#include "ui/events/devices/touchscreen_device.h" using content::BrowserThread; @@ -23,6 +27,9 @@ display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE; } +// TODO(felixe): More context at crbug.com/738885 +const uint16_t kDeviceIds[] = {0x0457, 0x266e}; + } // namespace OobeDisplayChooser::OobeDisplayChooser() : weak_ptr_factory_(this) {} @@ -51,18 +58,21 @@ void OobeDisplayChooser::MoveToTouchDisplay() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - const display::Displays& displays = - ash::Shell::Get()->display_manager()->active_only_display_list(); + const ui::DeviceDataManager* device_manager = + ui::DeviceDataManager::GetInstance(); + for (const ui::TouchscreenDevice& device : + device_manager->GetTouchscreenDevices()) { + if (!base::ContainsValue(kDeviceIds, device.vendor_id)) + continue; - if (displays.size() <= 1) - return; + int64_t display_id = + device_manager->GetTargetDisplayForTouchDevice(device.id); + if (display_id == display::kInvalidDisplayId) + continue; - for (const display::Display& display : displays) { - if (TouchSupportAvailable(display)) { - ash::Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId( - display.id()); - break; - } + ash::Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId( + display_id); + break; } }
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc index acf074ae..528fd1c 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h" #include <memory> +#include <vector> #include "ash/display/display_configuration_controller.h" #include "ash/shell.h" @@ -13,9 +14,12 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/display/display.h" #include "ui/display/display_observer.h" +#include "ui/display/manager/chromeos/touchscreen_util.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" +#include "ui/events/devices/device_data_manager.h" +#include "ui/events/devices/touchscreen_device.h" namespace chromeos { @@ -25,63 +29,93 @@ public: OobeDisplayChooserTest() : ash::test::AshTestBase() {} - void SetUp() override { - ash::test::AshTestBase::SetUp(); - display_manager_test_api_.reset( - new display::test::DisplayManagerTestApi(display_manager())); - } - - void EnableTouch(int64_t id) { - display_manager_test_api_->SetTouchSupport( - id, display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE); - } - - void DisableTouch(int64_t id) { - display_manager_test_api_->SetTouchSupport( - id, display::Display::TouchSupport::TOUCH_SUPPORT_UNAVAILABLE); - } - int64_t GetPrimaryDisplay() { return display::Screen::GetScreen()->GetPrimaryDisplay().id(); } - private: - std::unique_ptr<display::test::DisplayManagerTestApi> - display_manager_test_api_; + void UpdateTouchscreenDevices(const ui::TouchscreenDevice& touchscreen) { + std::vector<ui::TouchscreenDevice> devices{touchscreen}; + ui::DeviceHotplugEventObserver* manager = + ui::DeviceDataManager::GetInstance(); + manager->OnTouchscreenDevicesUpdated(devices); + } + + private: DISALLOW_COPY_AND_ASSIGN(OobeDisplayChooserTest); }; +const uint16_t kWhitelistedId = 0x266e; + } // namespace TEST_F(OobeDisplayChooserTest, PreferTouchAsPrimary) { - OobeDisplayChooser display_chooser; - - UpdateDisplay("3000x2000,800x600"); - display::DisplayIdList ids = display_manager()->GetCurrentDisplayIdList(); - DisableTouch(ids[0]); - EnableTouch(ids[1]); - - EXPECT_EQ(ids[0], GetPrimaryDisplay()); - display_chooser.TryToPlaceUiOnTouchDisplay(); + // Setup 2 displays, second one is intended to be a touch display + std::vector<display::ManagedDisplayInfo> display_info; + display_info.push_back( + display::ManagedDisplayInfo::CreateFromSpecWithID("0+0-3000x2000", 1)); + display_info.push_back( + display::ManagedDisplayInfo::CreateFromSpecWithID("3000+0-800x600", 2)); + display_manager()->OnNativeDisplaysChanged(display_info); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(ids[1], GetPrimaryDisplay()); + // Make sure the non-touch display is primary + ash::Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(1); + + // Setup corresponding TouchscreenDevice object + ui::TouchscreenDevice touchscreen = + ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, + "Touchscreen", gfx::Size(800, 600), 1); + touchscreen.vendor_id = kWhitelistedId; + UpdateTouchscreenDevices(touchscreen); + base::RunLoop().RunUntilIdle(); + + // Associate touchscreen device with display + display_info[1].AddInputDevice(touchscreen.id); + display_info[1].set_touch_support(display::Display::TOUCH_SUPPORT_AVAILABLE); + display_manager()->OnNativeDisplaysChanged(display_info); + base::RunLoop().RunUntilIdle(); + + OobeDisplayChooser display_chooser; + EXPECT_EQ(1, GetPrimaryDisplay()); + display_chooser.TryToPlaceUiOnTouchDisplay(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, GetPrimaryDisplay()); } -TEST_F(OobeDisplayChooserTest, AddingSecondTouchDisplayShouldbeNOP) { - OobeDisplayChooser display_chooser; - - UpdateDisplay("3000x2000,800x600"); - display::DisplayIdList ids = display_manager()->GetCurrentDisplayIdList(); - EnableTouch(ids[0]); - EnableTouch(ids[1]); - - EXPECT_EQ(ids[0], GetPrimaryDisplay()); - display_chooser.TryToPlaceUiOnTouchDisplay(); +TEST_F(OobeDisplayChooserTest, DontSwitchFromTouch) { + // Setup 2 displays, second one is intended to be a touch display + std::vector<display::ManagedDisplayInfo> display_info; + display_info.push_back( + display::ManagedDisplayInfo::CreateFromSpecWithID("0+0-3000x2000", 1)); + display_info.push_back( + display::ManagedDisplayInfo::CreateFromSpecWithID("3000+0-800x600", 2)); + display_info[0].set_touch_support(display::Display::TOUCH_SUPPORT_AVAILABLE); + display_manager()->OnNativeDisplaysChanged(display_info); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(ids[0], GetPrimaryDisplay()); + // Make sure the non-touch display is primary + ash::Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(1); + + // Setup corresponding TouchscreenDevice object + ui::TouchscreenDevice touchscreen = + ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, + "Touchscreen", gfx::Size(800, 600), 1); + touchscreen.vendor_id = kWhitelistedId; + UpdateTouchscreenDevices(touchscreen); + base::RunLoop().RunUntilIdle(); + + // Associate touchscreen device with display + display_info[1].AddInputDevice(touchscreen.id); + display_info[1].set_touch_support(display::Display::TOUCH_SUPPORT_AVAILABLE); + display_manager()->OnNativeDisplaysChanged(display_info); + base::RunLoop().RunUntilIdle(); + + OobeDisplayChooser display_chooser; + EXPECT_EQ(1, GetPrimaryDisplay()); + display_chooser.TryToPlaceUiOnTouchDisplay(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, GetPrimaryDisplay()); } } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index d2db7e5..94f7115 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -226,17 +226,12 @@ return path; } -bool IsKeyboardConnected() { - const std::vector<ui::InputDevice>& keyboards = - ui::InputDeviceManager::GetInstance()->GetKeyboardDevices(); - for (const ui::InputDevice& keyboard : keyboards) { - if (keyboard.type == ui::INPUT_DEVICE_INTERNAL || - keyboard.type == ui::INPUT_DEVICE_EXTERNAL) { - return true; - } - } - - return false; +bool IsRemoraRequisitioned() { + policy::DeviceCloudPolicyManagerChromeOS* policy_manager = + g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->GetDeviceCloudPolicyManager(); + return policy_manager && policy_manager->IsRemoraRequisition(); } } // namespace @@ -376,7 +371,7 @@ // TODO(felixe): Display iteration and primary display selection not supported // in Mash. See http://crbug.com/720917. - if (!ash_util::IsRunningInMash() && !IsKeyboardConnected()) + if (!ash_util::IsRunningInMash() && IsRemoraRequisitioned()) oobe_display_chooser_ = base::MakeUnique<OobeDisplayChooser>(); }
diff --git a/chrome/browser/ui/webui/conflicts_ui.cc b/chrome/browser/ui/webui/conflicts_ui.cc index 1789f0c..bf8f50a0c4 100644 --- a/chrome/browser/ui/webui/conflicts_ui.cc +++ b/chrome/browser/ui/webui/conflicts_ui.cc
@@ -6,7 +6,6 @@ #include "base/memory/ptr_util.h" #include "base/memory/ref_counted_memory.h" -#include "base/metrics/user_metrics.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/conflicts_handler.h" #include "chrome/browser/ui/webui/module_database_conflicts_handler.h" @@ -60,8 +59,6 @@ ConflictsUI::ConflictsUI(content::WebUI* web_ui) : content::WebUIController(web_ui) { - base::RecordAction(base::UserMetricsAction("ViewAboutConflicts")); - if (base::FeatureList::IsEnabled(features::kModuleDatabase)) { web_ui->AddMessageHandler( base::MakeUnique<ModuleDatabaseConflictsHandler>());
diff --git a/chrome/browser/ui/webui/conflicts_ui.h b/chrome/browser/ui/webui/conflicts_ui.h index 0618ae5..c13d471e 100644 --- a/chrome/browser/ui/webui/conflicts_ui.h +++ b/chrome/browser/ui/webui/conflicts_ui.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_WEBUI_CONFLICTS_UI_H_ #include "base/macros.h" -#include "build/build_config.h" #include "content/public/browser/web_ui_controller.h" #include "ui/base/layout.h"
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js index b54503f..32a910b4 100644 --- a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js +++ b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
@@ -516,6 +516,14 @@ OptionsDialogExtensionSettingsWebUITest.prototype = { __proto__: InstallGoodExtensionSettingsWebUITest.prototype, + setUp() { + InstallGoodExtensionSettingsWebUITest.prototype.setUp.call(this); + + // False positive on iframe hosting the <extensionoptions> guest view. + this.accessibilityAuditConfig.ignoreSelectors( + 'focusableElementNotVisibleAndNotAriaHidden', 'iframe'); + }, + /** @override */ browsePreload: ExtensionSettingsWebUITest.prototype.browsePreload + '?options=' + GOOD_EXTENSION_ID,
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc index 8965daf..e786d4c 100644 --- a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc +++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc
@@ -75,6 +75,10 @@ base::Bind(&ChromeCleanupHandler::HandleRestartComputer, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "setLogsUploadPermission", + base::Bind(&ChromeCleanupHandler::HandleSetLogsUploadPermission, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "startCleanup", base::Bind(&ChromeCleanupHandler::HandleStartCleanup, base::Unretained(this))); } @@ -116,6 +120,12 @@ base::Value("chrome-cleanup-on-reboot-required")); } +void ChromeCleanupHandler::OnLogsEnabledChanged(bool logs_enabled) { + CallJavascriptFunction("cr.webUIListenerCallback", + base::Value("chrome-cleanup-upload-permission-change"), + base::Value(logs_enabled)); +} + void ChromeCleanupHandler::HandleDismiss(const base::ListValue* args) { DCHECK_EQ(0U, args->GetSize()); @@ -134,6 +144,9 @@ base::FeatureList::IsEnabled(safe_browsing::kInBrowserCleanerUIFeature)); AllowJavascript(); + + // Send the current logs upload state. + OnLogsEnabledChanged(controller_->logs_enabled()); } void ChromeCleanupHandler::HandleRestartComputer(const base::ListValue* args) { @@ -141,16 +154,32 @@ CallJavascriptFunction("cr.webUIListenerCallback", base::Value("chrome-cleanup-on-dismiss")); - // TODO(proberge): Show a prompt to reboot the system. + + controller_->Reboot(); +} + +void ChromeCleanupHandler::HandleSetLogsUploadPermission( + const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + bool allow_logs_upload = false; + args->GetBoolean(0, &allow_logs_upload); + + controller_->SetLogsEnabled(allow_logs_upload); } void ChromeCleanupHandler::HandleStartCleanup(const base::ListValue* args) { - DCHECK_EQ(0U, args->GetSize()); + CHECK_EQ(1U, args->GetSize()); + bool allow_logs_upload = false; + args->GetBoolean(0, &allow_logs_upload); + + // The state is propagated to all open tabs and should be consistent. + DCHECK_EQ(controller_->logs_enabled(), allow_logs_upload); controller_->ReplyWithUserResponse( - // TODO(proberge): Send kAcceptedWithLogs or kAcceptedWithoutLogs based on - // the state of a logs upload permissions checkbox. - profile_, ChromeCleanerController::UserResponse::kAcceptedWithoutLogs); + profile_, + allow_logs_upload + ? ChromeCleanerController::UserResponse::kAcceptedWithLogs + : ChromeCleanerController::UserResponse::kAcceptedWithoutLogs); } } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h index e32b273..59f4493 100644 --- a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h +++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h
@@ -36,6 +36,7 @@ void OnInfected(const std::set<base::FilePath>& files) override; void OnCleaning(const std::set<base::FilePath>& files) override; void OnRebootRequired() override; + void OnLogsEnabledChanged(bool logs_enabled) override; private: // Callback for the "dismissCleanupPage" message to hide the Cleanup page @@ -51,6 +52,10 @@ // system restart. void HandleRestartComputer(const base::ListValue* args); + // Callback for the "setLogsUploadPermission" message to keep track of + // whether the user opted-out of logs upload or not. + void HandleSetLogsUploadPermission(const base::ListValue* args); + // Callback for the "startCleanup" message to start removing unwanted // software from the user's computer. void HandleStartCleanup(const base::ListValue* args);
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 dfb283f30..5c9dce3 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
@@ -788,6 +788,7 @@ {"chromeCleanupDoneButtonLabel", IDS_CHROME_CLEANUP_WEBUI_DONE_BUTTON_LABEL}, {"chromeCleanupLinkShowFiles", IDS_CHROME_CLEANUP_WEBUI_LINK_SHOW_FILES}, + {"chromeCleanupLogsUploadPermission", IDS_CHROME_CLEANUP_LOGS_PERMISSION}, {"chromeCleanupRemoveButtonLabel", IDS_CHROME_CLEANUP_WEBUI_REMOVE_BUTTON_LABEL}, {"chromeCleanupRestartButtonLabel", @@ -801,6 +802,12 @@ }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); + const std::string cleanup_learn_more_url = + google_util::AppendGoogleLocaleParam( + GURL(chrome::kChromeCleanerLearnMoreURL), + g_browser_process->GetApplicationLocale()) + .spec(); + html_source->AddString("chromeCleanupLearnMoreUrl", cleanup_learn_more_url); } #endif // defined(OS_WIN)
diff --git a/chrome/browser/ui/webui/signin/signin_error_handler.cc b/chrome/browser/ui/webui/signin/signin_error_handler.cc index 88e1f53..6824d82 100644 --- a/chrome/browser/ui/webui/signin/signin_error_handler.cc +++ b/chrome/browser/ui/webui/signin/signin_error_handler.cc
@@ -20,13 +20,11 @@ // |browser_| must not be null when this dialog is presented from the // user manager. DCHECK(browser_ || is_system_profile_); - if (!is_system_profile_) - BrowserList::AddObserver(this); + BrowserList::AddObserver(this); } SigninErrorHandler::~SigninErrorHandler() { - if (!is_system_profile_) - BrowserList::RemoveObserver(this); + BrowserList::RemoveObserver(this); } void SigninErrorHandler::OnBrowserRemoved(Browser* browser) { @@ -103,11 +101,16 @@ void SigninErrorHandler::CloseDialog() { if (is_system_profile_) { - // Avoid closing the user manager window when the error message is displayed - // without browser window. - UserManagerProfileDialog::HideDialog(); - } else { - if (browser_) - browser_->signin_view_controller()->CloseModalSignin(); + CloseUserManagerProfileDialog(); + } else if (browser_){ + CloseBrowserModalSigninDialog(); } } + +void SigninErrorHandler::CloseBrowserModalSigninDialog() { + browser_->signin_view_controller()->CloseModalSignin(); +} + +void SigninErrorHandler::CloseUserManagerProfileDialog() { + UserManagerProfileDialog::HideDialog(); +}
diff --git a/chrome/browser/ui/webui/signin/signin_error_handler.h b/chrome/browser/ui/webui/signin/signin_error_handler.h index 84e101f98..d6e21d7 100644 --- a/chrome/browser/ui/webui/signin/signin_error_handler.h +++ b/chrome/browser/ui/webui/signin/signin_error_handler.h
@@ -66,6 +66,16 @@ // its members after this call. void CloseDialog(); + // Closes the modal sign-in view dialog. + // + // Virtual, so that it can be overriden from unit tests. + virtual void CloseBrowserModalSigninDialog(); + + // Closes the user manager profile dialog. + // + // Virtual, so that it can be overriden from unit tests. + virtual void CloseUserManagerProfileDialog(); + private: // Weak reference to the browser that showed the sign-in error dialog. // This is null when this sign-in error dialog is presented from the user
diff --git a/chrome/browser/ui/webui/signin/signin_error_handler_unittest.cc b/chrome/browser/ui/webui/signin/signin_error_handler_unittest.cc new file mode 100644 index 0000000..a6687c9 --- /dev/null +++ b/chrome/browser/ui/webui/signin/signin_error_handler_unittest.cc
@@ -0,0 +1,179 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/signin/signin_error_handler.h" + +#include "base/memory/ptr_util.h" +#include "base/values.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/webui/signin/signin_error_ui.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/dialog_test_browser_window.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_web_ui.h" + +namespace { +const char kSigninErrorLearnMoreUrl[] = + "https://support.google.com/chrome/answer/1181420?"; + +class TestingSigninErrorHandler : public SigninErrorHandler { + public: + TestingSigninErrorHandler(Browser* browser, + bool is_system_profile, + content::WebUI* web_ui) + : SigninErrorHandler(browser, is_system_profile), + browser_modal_dialog_did_close_(false), + user_manager_profile_dialog_did_close_(false) { + set_web_ui(web_ui); + } + + void CloseBrowserModalSigninDialog() override { + browser_modal_dialog_did_close_ = true; + SigninErrorHandler::CloseBrowserModalSigninDialog(); + } + + void CloseUserManagerProfileDialog() override { + user_manager_profile_dialog_did_close_ = true; + SigninErrorHandler::CloseUserManagerProfileDialog(); + } + + using SigninErrorHandler::HandleSwitchToExistingProfile; + using SigninErrorHandler::HandleConfirm; + using SigninErrorHandler::HandleLearnMore; + using SigninErrorHandler::HandleInitializedWithSize; + + bool browser_modal_dialog_did_close() { + return browser_modal_dialog_did_close_; + } + + bool user_manager_profile_dialog_did_close() { + return user_manager_profile_dialog_did_close_; + } + + private: + bool browser_modal_dialog_did_close_; + bool user_manager_profile_dialog_did_close_; + + DISALLOW_COPY_AND_ASSIGN(TestingSigninErrorHandler); +}; + +class SigninErrorHandlerTest : public BrowserWithTestWindowTest { + public: + SigninErrorHandlerTest() + : web_ui_(new content::TestWebUI), handler_(nullptr) {} + + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + chrome::NewTab(browser()); + web_ui()->set_web_contents( + browser()->tab_strip_model()->GetActiveWebContents()); + signin_error_ui_.reset(new SigninErrorUI(web_ui())); + } + + void TearDown() override { + signin_error_ui_.reset(); + web_ui_.reset(); + BrowserWithTestWindowTest::TearDown(); + } + + void CreateHandlerInBrowser() { + DCHECK(!handler_); + auto handler = base::MakeUnique<TestingSigninErrorHandler>( + browser(), false /* is_system_profile */, web_ui()); + handler_ = handler.get(); + signin_error_ui_.reset(new SigninErrorUI(web_ui())); + web_ui()->AddMessageHandler(std::move(handler)); + } + + void CreateHandlerInUserManager() { + DCHECK(!handler_); + auto handler = base::MakeUnique<TestingSigninErrorHandler>( + nullptr /* browser */, true /* is_system_profile */, web_ui()); + handler_ = handler.get(); + web_ui()->AddMessageHandler(std::move(handler)); + } + + TestingSigninErrorHandler* handler() { return handler_; } + + content::TestWebUI* web_ui() { return web_ui_.get(); } + + // BrowserWithTestWindowTest + BrowserWindow* CreateBrowserWindow() override { + return new DialogTestBrowserWindow; + } + + private: + std::unique_ptr<content::TestWebUI> web_ui_; + std::unique_ptr<SigninErrorUI> signin_error_ui_; + TestingSigninErrorHandler* handler_; // Not owned. + + DISALLOW_COPY_AND_ASSIGN(SigninErrorHandlerTest); +}; + +TEST_F(SigninErrorHandlerTest, InBrowserHandleLearnMore) { + // Before the test, there is only one new tab opened. + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(1, tab_strip_model->count()); + EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), + tab_strip_model->GetActiveWebContents()->GetURL()); + + // Open learn more + CreateHandlerInBrowser(); + base::ListValue args; + handler()->HandleLearnMore(&args); + + // Dialog should be closed now. + EXPECT_TRUE(handler()->browser_modal_dialog_did_close()); + + // Verify that the learn more URL was opened. + EXPECT_EQ(2, tab_strip_model->count()); + EXPECT_EQ(GURL(kSigninErrorLearnMoreUrl), + tab_strip_model->GetActiveWebContents()->GetURL()); +} + +TEST_F(SigninErrorHandlerTest, InBrowserHandleLearnMoreAfterBrowserRemoved) { + // Before the test, there is only one new tab opened. + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(1, tab_strip_model->count()); + EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), + tab_strip_model->GetActiveWebContents()->GetURL()); + + // Inform the handler that the browser was removed; + CreateHandlerInBrowser(); + handler()->OnBrowserRemoved(browser()); + + // Open learn more + base::ListValue args; + handler()->HandleLearnMore(&args); + + // Dialog is not closed if the browser was removed. + EXPECT_FALSE(handler()->browser_modal_dialog_did_close()); + + // Verify that the learn more URL was not opened as the browser was removed. + EXPECT_EQ(1, tab_strip_model->count()); + EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), + tab_strip_model->GetActiveWebContents()->GetURL()); +} + +TEST_F(SigninErrorHandlerTest, InBrowserTestConfirm) { + CreateHandlerInBrowser(); + base::ListValue args; + handler()->HandleConfirm(&args); + + // Confirm simply closes the dialog. + EXPECT_TRUE(handler()->browser_modal_dialog_did_close()); +} + +TEST_F(SigninErrorHandlerTest, InUserManagerTestConfirm) { + CreateHandlerInUserManager(); + base::ListValue args; + handler()->HandleConfirm(&args); + + // Confirm simply closes the dialog. + EXPECT_TRUE(handler()->user_manager_profile_dialog_did_close()); +} + +} // namespace
diff --git a/chrome/browser/win/enumerate_modules_model.cc b/chrome/browser/win/enumerate_modules_model.cc index 84e8df2b..4b819277 100644 --- a/chrome/browser/win/enumerate_modules_model.cc +++ b/chrome/browser/win/enumerate_modules_model.cc
@@ -655,14 +655,6 @@ return list; } -GURL EnumerateModulesModel::GetConflictUrl() { - // For now, simply bring up the chrome://conflicts page, which has detailed - // information about each module. - if (ShouldShowConflictWarning()) - return GURL(L"chrome://conflicts"); - return GURL(); -} - EnumerateModulesModel::EnumerateModulesModel() : conflict_notification_acknowledged_(false), confirmed_bad_modules_detected_(0),
diff --git a/chrome/browser/win/enumerate_modules_model.h b/chrome/browser/win/enumerate_modules_model.h index 12a5041..cd2b1e0a 100644 --- a/chrome/browser/win/enumerate_modules_model.h +++ b/chrome/browser/win/enumerate_modules_model.h
@@ -302,12 +302,6 @@ // Gets the whole module list as a ListValue. std::unique_ptr<base::ListValue> GetModuleList(); - // Returns the site to which the user should be taken when the conflict bubble - // or app menu item is clicked. For now this is simply chrome://conflicts, - // which contains detailed information about conflicts. Returns an empty URL - // if there are no conficts. May only be called on UI thread. - GURL GetConflictUrl(); - private: friend class ModuleEnumerator;
diff --git a/chrome/common/media_router/mojo/BUILD.gn b/chrome/common/media_router/mojo/BUILD.gn index 3a24977..4fda4230 100644 --- a/chrome/common/media_router/mojo/BUILD.gn +++ b/chrome/common/media_router/mojo/BUILD.gn
@@ -35,6 +35,7 @@ public_deps = [ ":media_controller", + "//media/mojo/interfaces:mirror_service_remoting", "//mojo/common:common_custom_types", "//net/interfaces:interfaces", "//url/mojo:url_mojom_gurl",
diff --git a/chrome/common/media_router/mojo/media_router.mojom b/chrome/common/media_router/mojo/media_router.mojom index ce99ec3..5f53bc1 100644 --- a/chrome/common/media_router/mojo/media_router.mojom +++ b/chrome/common/media_router/mojo/media_router.mojom
@@ -6,6 +6,7 @@ import "chrome/common/media_router/mojo/media_controller.mojom"; import "chrome/common/media_router/mojo/media_status.mojom"; +import "media/mojo/interfaces/mirror_service_remoting.mojom"; import "mojo/common/time.mojom"; import "net/interfaces/ip_address.mojom"; import "url/mojo/origin.mojom"; @@ -474,4 +475,11 @@ // |messages|: A non-empty list of messages received. OnRouteMessagesReceived(string route_id, array<RouteMessage> messages); + + // Called when a MediaRemoter for a tab with |tab_id| is started. |remoter| + // can be used to access the MediaRemoter to control a media remoting session + // and send RPC messages to the remote device. |remoting_source| is bound to + // receive the updates/messages from MediaRemoter. + OnMediaRemoterCreated(int32 tab_id, media.mojom.MirrorServiceRemoter remoter, + media.mojom.MirrorServiceRemotingSource& remoting_source); };
diff --git a/chrome/common/safe_browsing/zip_analyzer.cc b/chrome/common/safe_browsing/zip_analyzer.cc index 5577157..50f3f25 100644 --- a/chrome/common/safe_browsing/zip_analyzer.cc +++ b/chrome/common/safe_browsing/zip_analyzer.cc
@@ -65,7 +65,7 @@ const base::FilePath& file_path, zip::ZipReader* reader, base::File* temp_file, - ClientDownloadRequest_ArchivedBinary* archived_binary) { + ClientDownloadRequest::ArchivedBinary* archived_binary) { std::string file_basename(file_path.BaseName().AsUTF8Unsafe()); if (base::StreamingUtf8Validator::Validate(file_basename)) archived_binary->set_file_basename(file_basename); @@ -121,6 +121,13 @@ DVLOG(2) << "Downloaded a zipped archive: " << file.value(); results->has_archive = true; archived_archive_filenames.insert(file.BaseName()); + ClientDownloadRequest::ArchivedBinary* archived_archive = + results->archived_binary.Add(); + std::string file_basename_utf8(file.BaseName().AsUTF8Unsafe()); + if (base::StreamingUtf8Validator::Validate(file_basename_utf8)) + archived_archive->set_file_basename(file_basename_utf8); + archived_archive->set_download_type( + ClientDownloadRequest::ZIPPED_ARCHIVE); } else if (FileTypePolicies::GetInstance()->IsCheckedBinaryFile(file)) { DVLOG(2) << "Downloaded a zipped executable: " << file.value(); results->has_executable = true;
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 1a4b7422..5303894 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -633,6 +633,10 @@ #if defined(OS_WIN) const char kNotificationsHelpURL[] = "https://support.google.com/chrome/?p=ui_notifications"; + +// TODO(proberge): Change this URL to a p-link. +const char kChromeCleanerLearnMoreURL[] = + "https://support.google.com/chrome/answer/6086368"; #endif const char kNotificationWelcomeLearnMoreURL[] =
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 8df1386c..38e1188 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -526,6 +526,9 @@ #if defined(OS_WIN) extern const char kNotificationsHelpURL[]; + +// The URL for the Learn More link in the Chrome Cleanup settings card. +extern const char kChromeCleanerLearnMoreURL[]; #endif // The Welcome Notification More Info URL.
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc index 881f5252..288de6377 100644 --- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc +++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -275,6 +275,11 @@ IDR_MOJO_IP_ADDRESS_MOJOM_JS); source_map->RegisterSource("url/mojo/origin.mojom", IDR_ORIGIN_MOJOM_JS); source_map->RegisterSource("url/mojo/url.mojom", IDR_MOJO_URL_MOJOM_JS); + source_map->RegisterSource("media/mojo/interfaces/remoting_common.mojom", + IDR_REMOTING_COMMON_JS); + source_map->RegisterSource( + "media/mojo/interfaces/mirror_service_remoting.mojom", + IDR_MEDIA_REMOTING_JS); // These bindings are unnecessary with native bindings enabled. if (!extensions::FeatureSwitch::native_crx_bindings()->IsEnabled()) {
diff --git a/chrome/renderer/resources/extensions/media_router_bindings.js b/chrome/renderer/resources/extensions/media_router_bindings.js index f001ed3f..263b5f70 100644 --- a/chrome/renderer/resources/extensions/media_router_bindings.js +++ b/chrome/renderer/resources/extensions/media_router_bindings.js
@@ -10,6 +10,8 @@ 'chrome/common/media_router/mojo/media_status.mojom', 'content/public/renderer/frame_interfaces', 'extensions/common/mojo/keep_alive.mojom', + 'media/mojo/interfaces/mirror_service_remoting.mojom', + 'media/mojo/interfaces/remoting_common.mojom', 'mojo/common/time.mojom', 'mojo/public/js/bindings', 'net/interfaces/ip_address.mojom', @@ -20,6 +22,8 @@ mediaStatusMojom, frameInterfaces, keepAliveMojom, + remotingMojom, + remotingCommonMojom, timeMojom, bindings, ipAddressMojom, @@ -279,11 +283,24 @@ MediaController: mediaControllerMojom.MediaController, MediaStatus: mediaStatusMojom.MediaStatus, MediaStatusObserverPtr: mediaStatusMojom.MediaStatusObserverPtr, + MirrorServiceRemoter: remotingMojom.MirrorServiceRemoter, + MirrorServiceRemoterPtr: remotingMojom.MirrorServiceRemoterPtr, + MirrorServiceRemotingSourcePtr: + remotingMojom.MirrorServiceRemotingSourcePtr, + RemotingStopReason: remotingCommonMojom.RemotingStopReason, + RemotingStartFailReason: remotingCommonMojom.RemotingStartFailReason, + RemotingSinkFeatures: remotingCommonMojom.RemotingSinkFeatures, + RemotingSinkAudioCapabilities: + remotingCommonMojom.RemotingSinkAudioCapabilities, + RemotingSinkVideoCapabilities: + remotingCommonMojom.RemotingSinkVideoCapabilities, + SinkCapabilities: remotingCommonMojom.SinkCapabilities, Origin: originMojom.Origin, Sink: mediaRouterMojom.MediaSink, SinkExtraData: mediaRouterMojom.MediaSinkExtraData, TimeDelta: timeMojom.TimeDelta, Url: urlMojom.Url, + makeRequest: bindings.makeRequest, }; }; @@ -465,6 +482,16 @@ }; /** + * @param {number} tabId + * @param {!remotingMojom.MirrorServiceRemoterPtr} remoter + * @param {!remotingMojom.MirrorServiceRemotingSourcePtr} remotingSource + */ + MediaRouter.prototype.onMediaRemoterCreated = function(tabId, remoter, + remotingSource) { + this.service_.onMediaRemoterCreated(tabId, remoter, remotingSource); + } + + /** * Object containing callbacks set by the provider manager. * * @constructor
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd index fef051c..67382cb7 100644 --- a/chrome/renderer/resources/renderer_resources.grd +++ b/chrome/renderer/resources/renderer_resources.grd
@@ -93,6 +93,8 @@ <include name="IDR_MOJO_IP_ADDRESS_MOJOM_JS" file="${mojom_root}\net\interfaces\ip_address.mojom.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_ORIGIN_MOJOM_JS" file="${mojom_root}\url\mojo\origin.mojom.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MOJO_URL_MOJOM_JS" file="${mojom_root}\url\mojo\url.mojom.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_MEDIA_REMOTING_JS" file="${mojom_root}\media\mojo\interfaces\mirror_service_remoting.mojom.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_REMOTING_COMMON_JS" file="${mojom_root}\media\mojo\interfaces\remoting_common.mojom.js" use_base_dir="false" type="BINDATA" /> </if> </includes> </release>
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index dec3005..22226b8 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2072,6 +2072,7 @@ "../browser/ui/views/payments/credit_card_editor_view_controller_browsertest.cc", "../browser/ui/views/payments/cvc_unmask_view_controller_browsertest.cc", "../browser/ui/views/payments/error_message_view_controller_browsertest.cc", + "../browser/ui/views/payments/modifiers_browsertest.cc", "../browser/ui/views/payments/order_summary_view_controller_browsertest.cc", "../browser/ui/views/payments/payment_method_view_controller_browsertest.cc", "../browser/ui/views/payments/payment_request_blob_url_browsertest.cc", @@ -3189,6 +3190,7 @@ "../browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/google_captcha_observer_unittest.cc", "../browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer_unittest.cc", + "../browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/lofi_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_unittest.cc", @@ -4797,6 +4799,7 @@ "../browser/signin/signin_global_error_unittest.cc", "../browser/signin/signin_util_unittest.cc", "../browser/ui/webui/signin/signin_create_profile_handler_unittest.cc", + "../browser/ui/webui/signin/signin_error_handler_unittest.cc", "../browser/ui/webui/signin/sync_confirmation_handler_unittest.cc", "../browser/upgrade_detector_impl_unittest.cc", ]
diff --git a/chrome/test/data/page_load_metrics/large_iframe.html b/chrome/test/data/page_load_metrics/large_iframe.html new file mode 100644 index 0000000..c6efc1a7 --- /dev/null +++ b/chrome/test/data/page_load_metrics/large_iframe.html
@@ -0,0 +1,5 @@ +<html> + <body> + <iframe src="large.html"></iframe> + </body> +</html>
diff --git a/chrome/test/data/payments/app.json b/chrome/test/data/payments/app.json new file mode 100644 index 0000000..bcb1ae68 --- /dev/null +++ b/chrome/test/data/payments/app.json
@@ -0,0 +1,12 @@ +{ + "name": "BobPay", + "related_applications": [{ + "platform": "play", + "id": "com.bobpay", + "min_version": "1", + "fingerprints": [{ + "type": "sha256_cert", + "value": "59:5C:88:65:FF:C4:E8:20:CF:F7:3E:C8:64:D0:95:F0:06:19:2E:A6:7B:20:04:D1:03:07:92:E2:A5:31:67:66" + }] + }] +}
diff --git a/chrome/test/data/payments/bobpay_and_basic_card_with_basic_card_modifiers.js b/chrome/test/data/payments/bobpay_and_basic_card_with_basic_card_modifiers.js new file mode 100644 index 0000000..de2ee33 --- /dev/null +++ b/chrome/test/data/payments/bobpay_and_basic_card_with_basic_card_modifiers.js
@@ -0,0 +1,237 @@ +/* + * 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. + */ + +/* global PaymentRequest:false */ + +/** + * Launches the PaymentRequest UI with Bob Pay and basic-card as payment + * methods and a modifier for basic-card + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'basic-card']}], + { + total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}, + modifiers: [{ + supportedMethods: ['basic-card'], + total: { + label: 'Total', + amount: {currency: 'USD', value: '4.00'}, + }, + additionalDisplayItems: [{ + label: 'basic-card discount', + amount: {currency: 'USD', value: '-1.00'}, + }], + data: {discountProgramParticipantId: '86328764873265'}, + }], + }) + .show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { + print(error.message); + }); + }) + .catch(function(error) { + print(error.message); + }); + } catch (error) { + print(error.message); + } +} + +/** + * Launches the PaymentRequest UI with Bob Pay and basic-card as payment + * methods and a modifier for basic-card with "credit" type + */ +function creditSupportedType() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'basic-card']}], + { + total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}, + modifiers: [{ + supportedMethods: ['basic-card'], + total: { + label: 'Total', + amount: {currency: 'USD', value: '4.00'}, + }, + additionalDisplayItems: [{ + label: 'basic-card discount', + amount: {currency: 'USD', value: '-1.00'}, + }], + data: { + discountProgramParticipantId: '86328764873265', + supportedTypes: ['credit'], + }, + }], + }) + .show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { + print(error.message); + }); + }) + .catch(function(error) { + print(error.message); + }); + } catch (error) { + print(error.message); + } +} + +/** + * Launches the PaymentRequest UI with Bob Pay and basic-card as payment + * methods and a modifier for basic-card with "debit" type + */ +function debitSupportedType() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'basic-card']}], + { + total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}, + modifiers: [{ + supportedMethods: ['basic-card'], + total: { + label: 'Total', + amount: {currency: 'USD', value: '4.00'}, + }, + additionalDisplayItems: [{ + label: 'basic-card discount', + amount: {currency: 'USD', value: '-1.00'}, + }], + data: { + discountProgramParticipantId: '86328764873265', + supportedTypes: ['debit'], + }, + }], + }) + .show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { + print(error.message); + }); + }) + .catch(function(error) { + print(error.message); + }); + } catch (error) { + print(error.message); + } +} + +/** + * Launches the PaymentRequest UI with Bob Pay and basic-card as payment + * methods and a modifier for basic-card with "credit" type and "visa" network + */ +function visaSupportedNetwork() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'basic-card']}], + { + total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}, + modifiers: [{ + supportedMethods: ['basic-card'], + total: { + label: 'Total', + amount: {currency: 'USD', value: '4.00'}, + }, + additionalDisplayItems: [{ + label: 'basic-card discount', + amount: {currency: 'USD', value: '-1.00'}, + }], + data: { + discountProgramParticipantId: '86328764873265', + supportedTypes: ['credit'], + supportedNetworks: ['visa'], + }, + }], + }) + .show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { + print(error.message); + }); + }) + .catch(function(error) { + print(error.message); + }); + } catch (error) { + print(error.message); + } +} + +/** + * Launches the PaymentRequest UI with Bob Pay and basic-card as payment + * methods and a modifier for basic-card with "credit" type and " mastercard" + * network + */ +function mastercardSupportedNetwork() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'basic-card']}], + { + total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}, + modifiers: [{ + supportedMethods: ['basic-card'], + total: { + label: 'Total', + amount: {currency: 'USD', value: '4.00'}, + }, + additionalDisplayItems: [{ + label: 'basic-card discount', + amount: {currency: 'USD', value: '-1.00'}, + }], + data: { + discountProgramParticipantId: '86328764873265', + supportedTypes: ['credit'], + supportedNetworks: ['mastercard'], + }, + }], + }) + .show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { + print(error.message); + }); + }) + .catch(function(error) { + print(error.message); + }); + } catch (error) { + print(error.message); + } +}
diff --git a/chrome/test/data/payments/metrics.js b/chrome/test/data/payments/metrics.js index 0edaa6a..753e387 100644 --- a/chrome/test/data/payments/metrics.js +++ b/chrome/test/data/payments/metrics.js
@@ -188,6 +188,47 @@ } /** + * Launches the PaymentRequest UI which accepts credit cards and Bob Pay. + */ +function cardsAndBobPayBuy() { // eslint-disable-line no-unused-vars + try { + request = new PaymentRequest( + [{ + supportedMethods: ['visa', 'https://bobpay.com'], + }], { + total: { + label: 'Total', + amount: { + currency: 'USD', + value: '5.00', + }, + }, + shippingOptions: [{ + id: 'freeShippingOption', + label: 'Free global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: true, + }], + }, { + requestShipping: true, + }); + request.show() + .then(function(resp) { + return resp.complete('success'); + }).then(function() { + print(JSON.stringify(resp, undefined, 2)); + }).catch(function(error) { + print(error); + }); + } catch (error) { + print(error.message); + } +} + +/** * Aborts the current PaymentRequest. */ function abort() { // eslint-disable-line no-unused-vars
diff --git a/chrome/test/data/payments/payment-manifest.json b/chrome/test/data/payments/payment-manifest.json new file mode 100644 index 0000000..cf1ba1ec --- /dev/null +++ b/chrome/test/data/payments/payment-manifest.json
@@ -0,0 +1,4 @@ +{ + "default_applications": ["app.json"], + "supported_origins": ["https://alicepay.com"] +}
diff --git a/chrome/test/data/payments/payment_request_bobpay_and_basic_card_with_basic_card_modifiers_test.html b/chrome/test/data/payments/payment_request_bobpay_and_basic_card_with_basic_card_modifiers_test.html new file mode 100644 index 0000000..624910d --- /dev/null +++ b/chrome/test/data/payments/payment_request_bobpay_and_basic_card_with_basic_card_modifiers_test.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<!-- +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. +--> +<html> +<head> +<title>Bob Pay and basic-card with Basic-Card modifiers Test</title> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> +<link rel="stylesheet" type="text/css" href="style.css"> +</head> +<body> +<button onclick="buy()" id="buy">Bob Pay and Basic-Card with Basic-Card modifiers Test</button> +<button onclick="creditSupportedType()" id="credit_supported_type">Bob Pay and Basic-Card with Basic-Card modifiers Test with credit supported type</button> +<button onclick="debitSupportedType()" id="debit_supported_type">Bob Pay and Basic-Card with Basic-Card modifiers Test with debit supported type</button> +<button onclick="visaSupportedNetwork()" id="visa_supported_network">Bob Pay and Basic-Card with Basic-Card modifiers Test with visa supported network</button> +<button onclick="mastercardSupportedNetwork()" id="mastercard_supported_network">Bob Pay and Basic-Card with Basic-Card modifiers Test with mastercard supported network</button> +<pre id="result"></pre> +<script src="util.js"></script> +<script src="bobpay_and_basic_card_with_basic_card_modifiers.js"></script> +</body> +</html>
diff --git a/chrome/test/data/payments/payment_request_metrics_test.html b/chrome/test/data/payments/payment_request_metrics_test.html index d567b4a..b8a8b14f 100644 --- a/chrome/test/data/payments/payment_request_metrics_test.html +++ b/chrome/test/data/payments/payment_request_metrics_test.html
@@ -11,10 +11,11 @@ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> </head> <body> -<button onclick="ccBuy()" id="ccBuy">CC Buy Test</button><br> -<button onclick="androidPayBuy()" id="androidPayBuy">Android Pay Buy Test</button><br> -<button onclick="androidPaySkipUiBuy()" id="androidPaySkipUiBuy">Android Pay Skip UI Buy Test</button><br> -<button onclick="noSupported()" id="noSupported">No Supported Method Test</button><br> +<div> <button onclick="ccBuy()" id="ccBuy">CC Buy Test</button> </div> +<div> <button onclick="androidPayBuy()" id="androidPayBuy">Android Pay Buy Test</button> </div> +<div> <button onclick="androidPaySkipUiBuy()" id="androidPaySkipUiBuy">Android Pay Skip UI Buy Test</button> </div> +<div> <button onclick="noSupported()" id="noSupported">No Supported Method Test</button> </div> +<div> <button onclick="cardsAndBobPayBuy()" id="cardsAndBobPayBuy">Android Pay Buy Test</button> </div> <button onclick="abort()" id="abort">Abort</button> <pre id="result"></pre> <script src="util.js"></script>
diff --git a/chrome/test/data/payments/webpay b/chrome/test/data/payments/webpay new file mode 100644 index 0000000..e0dfe7d --- /dev/null +++ b/chrome/test/data/payments/webpay
@@ -0,0 +1 @@ +<!-- Intentionally blank. -->
diff --git a/chrome/test/data/payments/webpay.mock-http-headers b/chrome/test/data/payments/webpay.mock-http-headers new file mode 100644 index 0000000..44e5a707 --- /dev/null +++ b/chrome/test/data/payments/webpay.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Link: <payment-manifest.json>; rel="payment-method-manifest"
diff --git a/chrome/test/data/webui/print_preview/plugin_stub.js b/chrome/test/data/webui/print_preview/plugin_stub.js new file mode 100644 index 0000000..1c141b9 --- /dev/null +++ b/chrome/test/data/webui/print_preview/plugin_stub.js
@@ -0,0 +1,55 @@ +// 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. + +cr.define('print_preview', function() { + /** + * Test version of the print preview PDF plugin + */ + class PDFPluginStub { + /** + * @param {!print_preview.PreviewArea} The PreviewArea that owns this + * plugin. + */ + constructor(area) { + /** + * @private {?Function} The callback to run when the plugin has loaded. + */ + this.loadCallback_ = null; + + /** @private {!EventTracker} The plugin stub's event tracker. */ + this.tracker_ = new EventTracker(); + + // Call documentLoadComplete as soon as the preview area starts the + // preview. + this.tracker_.add( + area, + print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS, + this.documentLoadComplete.bind(this)); + } + + /** + * @param {!Function} callback The callback to run when the plugin has + * loaded. + */ + setLoadCallback(callback) { + this.loadCallback_ = callback; + } + + documentLoadComplete() { + if (this.loadCallback_) + this.loadCallback_(); + } + + /** + * Stubbed out since some tests result in a call. + * @param {string} url The url to initialize the plugin to. + * @param {boolean} color Whether the preview should be in color. + * @param {!Array<number>} pages The pages to preview. + * @param {boolean} modifiable Whether the source document is modifiable. + */ + resetPrintPreviewMode(url, color, pages, modifiable) {} + } + + return {PDFPluginStub: PDFPluginStub}; +});
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js index e874df6..b38e99f6 100644 --- a/chrome/test/data/webui/print_preview/print_preview_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -302,7 +302,9 @@ print_preview.NativeLayer.setInstance(nativeLayer); printPreview = new print_preview.PrintPreview(); previewArea = printPreview.getPreviewArea(); - previewArea.setIsBrowserTest(true); + previewArea.plugin_ = new print_preview.PDFPluginStub(previewArea); + previewArea.plugin_.setLoadCallback( + previewArea.onPluginLoad_.bind(previewArea)); }); // Test some basic assumptions about the print preview WebUI.
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js index 929f107..af6eb5c 100644 --- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -58,6 +58,7 @@ ROOT_PATH + 'chrome/test/data/webui/test_browser_proxy.js', 'print_preview_tests.js', 'native_layer_stub.js', + 'plugin_stub.js', ], };
diff --git a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js index 9af4c29..6472b7c4 100644 --- a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js +++ b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
@@ -12,6 +12,7 @@ 'dismissCleanupPage', 'registerChromeCleanerObserver', 'restartComputer', + 'setLogsUploadPermission', 'startCleanup', ]); }; @@ -35,9 +36,14 @@ }, /** @override */ - startCleanup: function() { - this.methodCalled('startCleanup'); + setLogsUploadPermission: function(enabled) { + this.methodCalled('setLogsUploadPermission', enabled); }, + + /** @override */ + startCleanup: function(logsUploadEnabled) { + this.methodCalled('startCleanup', logsUploadEnabled); + } }; var chromeCleanupPage = null; @@ -61,6 +67,7 @@ }); test('startCleanupFromInfected', function() { + cr.webUIListenerCallback('chrome-cleanup-upload-permission-change', false); cr.webUIListenerCallback( 'chrome-cleanup-on-infected', ['file 1', 'file 2', 'file 3']); Polymer.dom.flush(); @@ -75,13 +82,15 @@ var actionButton = chromeCleanupPage.$$('#action-button'); assertTrue(!!actionButton); MockInteractions.tap(actionButton); - ChromeCleanupProxy.whenCalled('startCleanup').then(function() { - cr.webUIListenerCallback('chrome-cleanup-on-cleaning', false); - Polymer.dom.flush(); + ChromeCleanupProxy.whenCalled('startCleanup').then( + function(logsUploadEnabled) { + assertFalse(logsUploadEnabled); + cr.webUIListenerCallback('chrome-cleanup-on-cleaning', false); + Polymer.dom.flush(); - var spinner = chromeCleanupPage.$$('#cleaning-spinner'); - assertTrue(spinner.active); - }) + var spinner = chromeCleanupPage.$$('#cleaning-spinner'); + assertTrue(spinner.active); + }) }); test('rebootFromRebootRequired', function() { @@ -119,4 +128,24 @@ MockInteractions.tap(actionButton); return ChromeCleanupProxy.whenCalled('dismissCleanupPage'); }); + + test('setLogsUploadPermission', function() { + cr.webUIListenerCallback( + 'chrome-cleanup-on-infected', ['file 1', 'file 2', 'file 3']); + Polymer.dom.flush(); + + var control = chromeCleanupPage.$$('#chromeCleanupLogsUploadControl'); + assertTrue(!!control); + + cr.webUIListenerCallback('chrome-cleanup-upload-permission-change', true); + Polymer.dom.flush(); + assertTrue(control.checked); + + cr.webUIListenerCallback('chrome-cleanup-upload-permission-change', false); + Polymer.dom.flush(); + assertFalse(control.checked); + + // TODO(proberge): Mock tapping on |control| and verify that + // |setLogsUploadPermission| is called with the right argument. + }); });
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 3d10c9cd..cd88338 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -61,11 +61,7 @@ } if (!is_android && use_alsa) { - tests += [ - "//chromecast/media/cma/backend/alsa:cast_alsa_cma_backend_unittests", - "//chromecast/media/cma/backend/alsa:libcast_governor_unittests", - "//chromecast/media/cma/backend/alsa:slew_volume_unittests", - ] + tests += [ "//chromecast/media/cma/backend/alsa:cast_alsa_cma_backend_unittests" ] } if (!is_android) {
diff --git a/chromecast/media/cma/backend/alsa/BUILD.gn b/chromecast/media/cma/backend/alsa/BUILD.gn index b87f10a..ea6399b1 100644 --- a/chromecast/media/cma/backend/alsa/BUILD.gn +++ b/chromecast/media/cma/backend/alsa/BUILD.gn
@@ -27,6 +27,7 @@ deps = [ ":alsa_cma_backend", + ":post_processor_factory", "//base", "//chromecast/base", "//chromecast/public", @@ -64,6 +65,7 @@ deps = [ ":alsa_features", ":slew_volume", + ":volume_map", "//base", "//chromecast/base", "//chromecast/media/base", @@ -76,6 +78,19 @@ ] } +source_set("volume_map") { + sources = [ + "cast_audio_json.cc", + "cast_audio_json.h", + "volume_map.cc", + "volume_map.h", + ] + deps = [ + "//base", + "//chromecast/base", + ] +} + source_set("slew_volume") { sources = [ "slew_volume.cc", @@ -101,14 +116,24 @@ test("cast_alsa_cma_backend_unittests") { sources = [ "filter_group_unittest.cc", + "post_processors/governor_unittest.cc", + "post_processors/saturated_gain_unittest.cc", + "slew_volume_unittests.cc", "stream_mixer_alsa_unittest.cc", ] deps = [ + ":governor", + ":libcast_governor_1.0", + ":libcast_saturated_gain_1.0", + ":post_processor_factory", + ":post_processor_test_support", + ":slew_volume", ":test_support", "//base", "//base/test:run_all_unittests", "//chromecast/media", + "//chromecast/public", "//media", "//media:shared_memory_support", "//testing/gmock", @@ -135,36 +160,15 @@ ] } -test("slew_volume_unittests") { - sources = [ - "slew_volume_unittests.cc", - ] - deps = [ - ":slew_volume", - "//base", - "//base/test:run_all_unittests", - "//media", - "//testing/gtest", - ] -} - +# This is separate from ":governor" because the associated unittest needs +# to create a Governor directly (to use test functions). shared_library("libcast_governor_1.0") { - deps = [ - ":governor", - ] -} - -test("libcast_governor_unittests") { sources = [ - "post_processors/governor_unittest.cc", + "post_processors/governor_create.cc", ] deps = [ ":governor", - ":post_processor_test_support", - "//base", - "//base/test:run_all_unittests", - "//media", - "//testing/gtest", + "//chromecast/public/media", ] } @@ -182,6 +186,20 @@ public_configs = [ "//chromecast/public:public_config" ] } +shared_library("libcast_saturated_gain_1.0") { + sources = [ + "post_processors/saturated_gain.cc", + "post_processors/saturated_gain.h", + ] + deps = [ + ":slew_volume", + ":volume_map", + "//base", + "//chromecast/base", + "//chromecast/public/media", + ] +} + source_set("post_processor_test_support") { testonly = true sources = [ @@ -194,3 +212,14 @@ "//testing/gtest", ] } + +source_set("post_processor_factory") { + sources = [ + "post_processor_factory.cc", + "post_processor_factory.h", + ] + deps = [ + "//base", + "//chromecast/public/media", + ] +}
diff --git a/chromecast/media/cma/backend/alsa/cast_audio_json.cc b/chromecast/media/cma/backend/alsa/cast_audio_json.cc new file mode 100644 index 0000000..57ad7bb --- /dev/null +++ b/chromecast/media/cma/backend/alsa/cast_audio_json.cc
@@ -0,0 +1,13 @@ +// 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 "chromecast/media/cma/backend/alsa/cast_audio_json.h" + +namespace chromecast { +namespace media { + +const char kCastAudioJsonFilePath[] = "/etc/cast_audio.json"; + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/alsa/cast_audio_json.h b/chromecast/media/cma/backend/alsa/cast_audio_json.h new file mode 100644 index 0000000..abfaacb --- /dev/null +++ b/chromecast/media/cma/backend/alsa/cast_audio_json.h
@@ -0,0 +1,16 @@ +// 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 CHROMECAST_MEDIA_CMA_BACKEND_ALSA_CAST_AUDIO_JSON_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_ALSA_CAST_AUDIO_JSON_H_ + +namespace chromecast { +namespace media { + +extern const char kCastAudioJsonFilePath[]; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_ALSA_CAST_AUDIO_JSON_H_
diff --git a/chromecast/media/cma/backend/alsa/cast_media_shlib.cc b/chromecast/media/cma/backend/alsa/cast_media_shlib.cc index 4a2d49c3..6e2bda6 100644 --- a/chromecast/media/cma/backend/alsa/cast_media_shlib.cc +++ b/chromecast/media/cma/backend/alsa/cast_media_shlib.cc
@@ -198,8 +198,9 @@ LoopbackAudioObserver* observer) { StreamMixerAlsa::Get()->RemoveLoopbackAudioObserver(observer); } -void SetPostProcessorConfig(const std::string& name, - const std::string& config) { + +void CastMediaShlib::SetPostProcessorConfig(const std::string& name, + const std::string& config) { StreamMixerAlsa::Get()->SetPostProcessorConfig(name, config); }
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc index 61a91772..c465d8d 100644 --- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc +++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc
@@ -21,13 +21,10 @@ namespace { const int kNoSampleRate = -1; -const char kSoCreateFunction[] = "AudioPostProcessorShlib_Create"; const char kProcessorKey[] = "processor"; const char kNameKey[] = "name"; } // namespace -using CreatePostProcessor = AudioPostProcessor* (*)(const std::string&, int); - std::unique_ptr<PostProcessingPipeline> PostProcessingPipeline::Create( const std::string& name, const base::ListValue* filter_description_list, @@ -67,22 +64,16 @@ const base::Value* processor_config_val; CHECK(processor_description_dict->Get("config", &processor_config_val)); CHECK(processor_config_val->is_dict() || processor_config_val->is_string()); - auto processor_config_string = SerializeToJson(*processor_config_val); + std::unique_ptr<std::string> processor_config_string = + SerializeToJson(*processor_config_val); LOG(INFO) << "Creating an instance of " << library_path << "(" << *processor_config_string << ")"; - libraries_.push_back(base::MakeUnique<base::ScopedNativeLibrary>( - base::FilePath(library_path))); - CHECK(libraries_.back()->is_valid()) - << "Could not open post processing library " << library_path; - CreatePostProcessor create = reinterpret_cast<CreatePostProcessor>( - libraries_.back()->GetFunctionPointer(kSoCreateFunction)); - CHECK(create) << "Could not find " << kSoCreateFunction << "() in " - << library_path; - processors_.emplace_back(PostProcessorInfo{ - base::WrapUnique(create(*processor_config_string, channels)), - processor_name}); + processors_.emplace_back( + PostProcessorInfo{factory_.CreatePostProcessor( + library_path, *processor_config_string, channels), + processor_name}); } }
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h index 75a9463..43b4374 100644 --- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h +++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h
@@ -11,10 +11,10 @@ #include "base/macros.h" #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h" +#include "chromecast/media/cma/backend/alsa/post_processor_factory.h" namespace base { class ListValue; -class ScopedNativeLibrary; } // namespace base namespace chromecast { @@ -44,6 +44,13 @@ const std::string& config) override; private: + // Note: typedef is used to silence chromium-style mandatory constructor in + // structs. + typedef struct { + std::unique_ptr<AudioPostProcessor> ptr; + std::string name; + } PostProcessorInfo; + int GetRingingTimeInFrames(); void UpdateCastVolume(float multiplier); @@ -55,17 +62,8 @@ float current_multiplier_; float cast_volume_; - // Contains all libraries in use; - // Functions in shared objects cannot be used once library is closed. - std::vector<std::unique_ptr<base::ScopedNativeLibrary>> libraries_; - - // Must be after libraries_ - // Note: typedef is used to silence chromium-style mandatory constructor in - // structs. - typedef struct { - std::unique_ptr<AudioPostProcessor> ptr; - std::string name; - } PostProcessorInfo; + // factory_ keeps shared libraries open, so it must outlive processors_. + PostProcessorFactory factory_; std::vector<PostProcessorInfo> processors_;
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc index d4128e1..2ad80d6 100644 --- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc +++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc
@@ -10,6 +10,7 @@ #include "base/values.h" #include "chromecast/base/serializers.h" #include "chromecast/media/base/audio_device_ids.h" +#include "chromecast/media/cma/backend/alsa/cast_audio_json.h" #include "media/audio/audio_device_description.h" namespace chromecast { @@ -26,8 +27,6 @@ } // namespace -const char kCastAudioConfigFilePath[] = "/etc/cast_audio.json"; - StreamPipelineDescriptor::StreamPipelineDescriptor( const base::ListValue* pipeline_in, const std::unordered_set<std::string>& stream_types_in) @@ -43,20 +42,20 @@ const std::string& json) : postprocessor_config_(nullptr) { if (json.empty() && - !base::PathExists(base::FilePath(kCastAudioConfigFilePath))) { + !base::PathExists(base::FilePath(kCastAudioJsonFilePath))) { LOG(WARNING) << "Could not open post-processing config in " - << kCastAudioConfigFilePath << "."; + << kCastAudioJsonFilePath << "."; return; } if (json.empty()) { config_dict_ = base::DictionaryValue::From( - DeserializeJsonFromFile(base::FilePath(kCastAudioConfigFilePath))); + DeserializeJsonFromFile(base::FilePath(kCastAudioJsonFilePath))); } else { config_dict_ = base::DictionaryValue::From(DeserializeFromJson(json)); } - CHECK(config_dict_) << "Invalid JSON in " << kCastAudioConfigFilePath; + CHECK(config_dict_) << "Invalid JSON in " << kCastAudioJsonFilePath; if (!config_dict_->GetDictionary(kPostProcessorsKey, &postprocessor_config_)) { LOG(WARNING) << "No post-processor config found."; @@ -98,10 +97,6 @@ return descriptors; } -std::string PostProcessingPipelineParser::GetFilePath() { - return kCastAudioConfigFilePath; -} - const base::ListValue* PostProcessingPipelineParser::GetMixPipeline() { return GetPipelineByKey(kMixPipelineKey); } @@ -116,7 +111,7 @@ if (!postprocessor_config_ || !postprocessor_config_->GetDictionary(key, &stream_dict)) { LOG(WARNING) << "No post-processor description found for \"" << key - << "\" in " << kCastAudioConfigFilePath + << "\" in " << kCastAudioJsonFilePath << ". Using passthrough."; return nullptr; }
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h index 76f11bbf1..e75f872df 100644 --- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h +++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h
@@ -55,8 +55,6 @@ const base::ListValue* GetMixPipeline(); const base::ListValue* GetLinearizePipeline(); - static std::string GetFilePath(); - private: const base::ListValue* GetPipelineByKey(const std::string& key);
diff --git a/chromecast/media/cma/backend/alsa/post_processor_factory.cc b/chromecast/media/cma/backend/alsa/post_processor_factory.cc new file mode 100644 index 0000000..c2f5379 --- /dev/null +++ b/chromecast/media/cma/backend/alsa/post_processor_factory.cc
@@ -0,0 +1,44 @@ +// 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 "chromecast/media/cma/backend/alsa/post_processor_factory.h" + +#include "base/files/file_path.h" +#include "base/memory/ptr_util.h" +#include "base/scoped_native_library.h" +#include "chromecast/public/media/audio_post_processor_shlib.h" + +namespace chromecast { +namespace media { + +namespace { + +const char kSoCreateFunction[] = "AudioPostProcessorShlib_Create"; + +} // namespace + +using CreatePostProcessorFunction = AudioPostProcessor* (*)(const std::string&, + int); + +PostProcessorFactory::PostProcessorFactory() = default; +PostProcessorFactory::~PostProcessorFactory() = default; + +std::unique_ptr<AudioPostProcessor> PostProcessorFactory::CreatePostProcessor( + const std::string& library_path, + const std::string& config, + int channels) { + libraries_.push_back(base::MakeUnique<base::ScopedNativeLibrary>( + base::FilePath(library_path))); + CHECK(libraries_.back()->is_valid()) + << "Could not open post processing library " << library_path; + auto create = reinterpret_cast<CreatePostProcessorFunction>( + libraries_.back()->GetFunctionPointer(kSoCreateFunction)); + + CHECK(create) << "Could not find " << kSoCreateFunction << "() in " + << library_path; + return base::WrapUnique(create(config, channels)); +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/alsa/post_processor_factory.h b/chromecast/media/cma/backend/alsa/post_processor_factory.h new file mode 100644 index 0000000..b21352c --- /dev/null +++ b/chromecast/media/cma/backend/alsa/post_processor_factory.h
@@ -0,0 +1,44 @@ +// 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 CHROMECAST_MEDIA_CMA_BACKEND_ALSA_POST_PROCESSOR_FACTORY_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_ALSA_POST_PROCESSOR_FACTORY_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" + +namespace base { +class ScopedNativeLibrary; +} // namespace base + +namespace chromecast { +namespace media { + +class AudioPostProcessor; + +class PostProcessorFactory { + public: + PostProcessorFactory(); + ~PostProcessorFactory(); + + std::unique_ptr<AudioPostProcessor> CreatePostProcessor( + const std::string& so_name, + const std::string& config, + int channels); + + private: + // Contains all libraries in use; + // Functions in shared objects cannot be used once library is closed. + std::vector<std::unique_ptr<base::ScopedNativeLibrary>> libraries_; + + DISALLOW_COPY_AND_ASSIGN(PostProcessorFactory); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_ALSA_POST_PROCESSOR_FACTORY_H_
diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor.cc b/chromecast/media/cma/backend/alsa/post_processors/governor.cc index 83299966..1718ca8 100644 --- a/chromecast/media/cma/backend/alsa/post_processors/governor.cc +++ b/chromecast/media/cma/backend/alsa/post_processors/governor.cc
@@ -75,10 +75,3 @@ } // namespace media } // namespace chromecast - -chromecast::media::AudioPostProcessor* AudioPostProcessorShlib_Create( - const std::string& config, - int channels) { - return static_cast<chromecast::media::AudioPostProcessor*>( - new chromecast::media::Governor(config, channels)); -}
diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor_create.cc b/chromecast/media/cma/backend/alsa/post_processors/governor_create.cc new file mode 100644 index 0000000..358a0eea --- /dev/null +++ b/chromecast/media/cma/backend/alsa/post_processors/governor_create.cc
@@ -0,0 +1,13 @@ +// 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 "chromecast/media/cma/backend/alsa/post_processors/governor.h" +#include "chromecast/public/media/audio_post_processor_shlib.h" + +chromecast::media::AudioPostProcessor* AudioPostProcessorShlib_Create( + const std::string& config, + int channels) { + return static_cast<chromecast::media::AudioPostProcessor*>( + new chromecast::media::Governor(config, channels)); +}
diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc b/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc index 38cac53f..7acf623 100644 --- a/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc +++ b/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc
@@ -11,10 +11,9 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" +#include "chromecast/media/cma/backend/alsa/post_processor_factory.h" #include "chromecast/media/cma/backend/alsa/post_processors/governor.h" #include "chromecast/media/cma/backend/alsa/post_processors/post_processor_unittest.h" -#include "media/base/audio_bus.h" -#include "media/base/audio_sample_types.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromecast { @@ -26,6 +25,7 @@ const char* kConfigTemplate = R"config({"onset_volume": %f, "clamp_multiplier": %f})config"; +const char kLibraryPath[] = "libcast_governor_1.0.so"; const float kDefaultClamp = 0.6f; const int kNumFrames = 100; const int kFrequency = 2000; @@ -111,24 +111,24 @@ ::testing::Values(0.0f, 0.1f, 0.5f, 0.9f, 1.0f, 1.1f)); // Default tests from post_processor_test -TEST_P(PostProcessorTest, TestDelay) { +TEST_P(PostProcessorTest, GovernorDelay) { std::string config = MakeConfigString(1.0, 1.0); - auto pp = - base::WrapUnique(AudioPostProcessorShlib_Create(config, kNumChannels)); + PostProcessorFactory factory; + auto pp = factory.CreatePostProcessor(kLibraryPath, config, kNumChannels); TestDelay(pp.get(), sample_rate_); } -TEST_P(PostProcessorTest, TestRinging) { +TEST_P(PostProcessorTest, GovernorRinging) { std::string config = MakeConfigString(1.0, 1.0); - auto pp = - base::WrapUnique(AudioPostProcessorShlib_Create(config, kNumChannels)); + PostProcessorFactory factory; + auto pp = factory.CreatePostProcessor(kLibraryPath, config, kNumChannels); TestRingingTime(pp.get(), sample_rate_); } -TEST_P(PostProcessorTest, TestPassthrough) { +TEST_P(PostProcessorTest, GovernorPassthrough) { std::string config = MakeConfigString(1.0, 1.0); - auto pp = - base::WrapUnique(AudioPostProcessorShlib_Create(config, kNumChannels)); + PostProcessorFactory factory; + auto pp = factory.CreatePostProcessor(kLibraryPath, config, kNumChannels); TestPassthrough(pp.get(), sample_rate_); }
diff --git a/chromecast/media/cma/backend/alsa/post_processors/saturated_gain.cc b/chromecast/media/cma/backend/alsa/post_processors/saturated_gain.cc new file mode 100644 index 0000000..a2d15e8 --- /dev/null +++ b/chromecast/media/cma/backend/alsa/post_processors/saturated_gain.cc
@@ -0,0 +1,73 @@ +// 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 "chromecast/media/cma/backend/alsa/post_processors/saturated_gain.h" + +#include <algorithm> +#include <cmath> + +#include "base/logging.h" +#include "base/values.h" +#include "chromecast/base/serializers.h" +#include "chromecast/media/cma/backend/alsa/slew_volume.h" + +namespace chromecast { +namespace media { + +namespace { +const int kNoSampleRate = -1; + +// Configuration strings: +const char kGainKey[] = "gain_db"; + +float DbFsToScale(float db) { + return std::pow(10, db / 20); +} + +} // namespace + +SaturatedGain::SaturatedGain(const std::string& config, int channels) + : channels_(channels), sample_rate_(kNoSampleRate), last_volume_(-1) { + auto config_dict = base::DictionaryValue::From(DeserializeFromJson(config)); + CHECK(config_dict) << "SaturatedGain config is not valid json: " << config; + double gain_db; + CHECK(config_dict->GetDouble(kGainKey, &gain_db)) << config; + gain_ = DbFsToScale(gain_db); + LOG(INFO) << "Created a SaturatedGain: gain = " << gain_db; +} + +SaturatedGain::~SaturatedGain() = default; + +bool SaturatedGain::SetSampleRate(int sample_rate) { + sample_rate_ = sample_rate; + slew_volume_.SetSampleRate(sample_rate); + return true; +} + +int SaturatedGain::ProcessFrames(float* data, int frames, float volume) { + if (volume != last_volume_) { + last_volume_ = volume; + // Don't apply more gain than attenuation. + float effective_gain = std::min( + 1.0f / DbFsToScale(volume_map_.VolumeToDbFS(last_volume_)), gain_); + slew_volume_.SetVolume(effective_gain); + } + + slew_volume_.ProcessFMUL(false, data, frames, channels_, data); + + return 0; // No delay in this pipeline. +} + +int SaturatedGain::GetRingingTimeInFrames() { + return 0; +} + +} // namespace media +} // namespace chromecast + +chromecast::media::AudioPostProcessor* AudioPostProcessorShlib_Create( + const std::string& config, + int channels) { + return new chromecast::media::SaturatedGain(config, channels); +}
diff --git a/chromecast/media/cma/backend/alsa/post_processors/saturated_gain.h b/chromecast/media/cma/backend/alsa/post_processors/saturated_gain.h new file mode 100644 index 0000000..51e195d --- /dev/null +++ b/chromecast/media/cma/backend/alsa/post_processors/saturated_gain.h
@@ -0,0 +1,43 @@ +// 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 CHROMECAST_MEDIA_CMA_BACKEND_ALSA_POST_PROCESSORS_SATURATED_GAIN_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_ALSA_POST_PROCESSORS_SATURATED_GAIN_H_ + +#include <string> + +#include "base/macros.h" +#include "chromecast/media/cma/backend/alsa/slew_volume.h" +#include "chromecast/media/cma/backend/alsa/volume_map.h" +#include "chromecast/public/media/audio_post_processor_shlib.h" + +namespace chromecast { +namespace media { + +// Provides a simple gain, avoiding overflow. +class SaturatedGain : public AudioPostProcessor { + public: + SaturatedGain(const std::string& config, int channels); + ~SaturatedGain() override; + + // AudioPostProcessor implementation: + bool SetSampleRate(int sample_rate) override; + int ProcessFrames(float* data, int frames, float volume) override; + int GetRingingTimeInFrames() override; + + private: + int channels_; + int sample_rate_; + float last_volume_; + VolumeMap volume_map_; + SlewVolume slew_volume_; + float gain_; + + DISALLOW_COPY_AND_ASSIGN(SaturatedGain); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_ALSA_POST_PROCESSORS_SATURATED_GAIN_H_
diff --git a/chromecast/media/cma/backend/alsa/post_processors/saturated_gain_unittest.cc b/chromecast/media/cma/backend/alsa/post_processors/saturated_gain_unittest.cc new file mode 100644 index 0000000..bad7b96e --- /dev/null +++ b/chromecast/media/cma/backend/alsa/post_processors/saturated_gain_unittest.cc
@@ -0,0 +1,54 @@ +// 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 <string> +#include <vector> + +#include "base/strings/stringprintf.h" +#include "chromecast/media/cma/backend/alsa/post_processor_factory.h" +#include "chromecast/media/cma/backend/alsa/post_processors/post_processor_unittest.h" + +namespace chromecast { +namespace media { +namespace post_processor_test { + +namespace { + +const char kConfigTemplate[] = + R"config({"gain_db": %f})config"; + +const char kLibraryPath[] = "libcast_saturated_gain_1.0.so"; + +std::string MakeConfigString(float gain_db) { + return base::StringPrintf(kConfigTemplate, gain_db); +} + +} // namespace + +// Default tests from post_processor_test +TEST_P(PostProcessorTest, SaturatedGainDelay) { + PostProcessorFactory factory; + std::string config = MakeConfigString(0.0); + auto pp = factory.CreatePostProcessor(kLibraryPath, config, kNumChannels); + TestDelay(pp.get(), sample_rate_); +} + +TEST_P(PostProcessorTest, SaturatedGainRinging) { + PostProcessorFactory factory; + std::string config = MakeConfigString(0.0); + auto pp = factory.CreatePostProcessor(kLibraryPath, config, kNumChannels); + TestRingingTime(pp.get(), sample_rate_); +} + +// Also tests clipping (by attempting to set gain way too high). +TEST_P(PostProcessorTest, SaturatedGainPassthrough) { + PostProcessorFactory factory; + std::string config = MakeConfigString(100.0); + auto pp = factory.CreatePostProcessor(kLibraryPath, config, kNumChannels); + TestPassthrough(pp.get(), sample_rate_); +} + +} // namespace post_processor_test +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc index daab40ef..a9f38bc 100644 --- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc +++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
@@ -24,6 +24,7 @@ #include "chromecast/base/chromecast_switches.h" #include "chromecast/media/base/audio_device_ids.h" #include "chromecast/media/cma/backend/alsa/alsa_wrapper.h" +#include "chromecast/media/cma/backend/alsa/cast_audio_json.h" #include "chromecast/media/cma/backend/alsa/filter_group.h" #include "chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h" #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h" @@ -277,7 +278,7 @@ << "media/audio/audio_device_description.cc"; CHECK(used_streams.insert(stream_type).second) << "Multiple instances of stream type '" << stream_type << "' in " - << pipeline_parser->GetFilePath() << "."; + << kCastAudioJsonFilePath << "."; } filter_groups_.push_back(base::MakeUnique<FilterGroup>( kNumInputChannels, false /* mono_mixer */, @@ -1086,10 +1087,10 @@ } void StreamMixerAlsa::SetPostProcessorConfig(const std::string& name, - const std::string& message) { - RUN_ON_MIXER_THREAD(&StreamMixerAlsa::SetPostProcessorConfig, name, message); + const std::string& config) { + RUN_ON_MIXER_THREAD(&StreamMixerAlsa::SetPostProcessorConfig, name, config); for (auto&& filter_group : filter_groups_) { - filter_group->SetPostProcessorConfig(name, message); + filter_group->SetPostProcessorConfig(name, config); } }
diff --git a/chromecast/media/cma/backend/alsa/volume_control.cc b/chromecast/media/cma/backend/alsa/volume_control.cc index 7ab9875..4146847 100644 --- a/chromecast/media/cma/backend/alsa/volume_control.cc +++ b/chromecast/media/cma/backend/alsa/volume_control.cc
@@ -30,8 +30,10 @@ #include "chromecast/base/serializers.h" #include "chromecast/media/cma/backend/alsa/alsa_features.h" #include "chromecast/media/cma/backend/alsa/alsa_volume_control.h" +#include "chromecast/media/cma/backend/alsa/cast_audio_json.h" #include "chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h" #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h" +#include "chromecast/media/cma/backend/alsa/volume_map.h" namespace chromecast { namespace media { @@ -47,22 +49,8 @@ constexpr char kKeyMediaDbFS[] = "dbfs.media"; constexpr char kKeyAlarmDbFS[] = "dbfs.alarm"; constexpr char kKeyCommunicationDbFS[] = "dbfs.communication"; -constexpr char kKeyVolumeMap[] = "volume_map"; -constexpr char kKeyLevel[] = "level"; -constexpr char kKeyDb[] = "db"; constexpr char kKeyDefaultVolume[] = "default_volume"; -struct LevelToDb { - float level; - float db; -}; - -const LevelToDb kDefaultVolumeMap[] = {{0.0f, kMinDbFS}, - {0.01f, -58.0f}, - {0.090909f, -48.0f}, - {0.818182f, -8.0f}, - {1.0f, 0.0f}}; - float DbFsToScale(float db) { if (db <= kMinDbFS) { return 0.0f; @@ -81,103 +69,6 @@ } } -class VolumeMap { - public: - VolumeMap() { - auto cast_audio_config = DeserializeJsonFromFile( - base::FilePath(PostProcessingPipelineParser::GetFilePath())); - const base::DictionaryValue* cast_audio_dict; - if (!cast_audio_config || - !cast_audio_config->GetAsDictionary(&cast_audio_dict)) { - LOG(WARNING) << "No cast audio config found; using default volume map."; - volume_map_.insert(volume_map_.end(), kDefaultVolumeMap, - kDefaultVolumeMap + arraysize(kDefaultVolumeMap)); - return; - } - - const base::ListValue* volume_map_list; - if (!cast_audio_dict->GetList(kKeyVolumeMap, &volume_map_list)) { - LOG(WARNING) << "No volume map found; using default volume map."; - volume_map_.insert(volume_map_.end(), kDefaultVolumeMap, - kDefaultVolumeMap + arraysize(kDefaultVolumeMap)); - return; - } - - double prev_level = -1.0; - for (size_t i = 0; i < volume_map_list->GetSize(); ++i) { - const base::DictionaryValue* volume_map_entry; - CHECK(volume_map_list->GetDictionary(i, &volume_map_entry)); - - double level; - CHECK(volume_map_entry->GetDouble(kKeyLevel, &level)); - CHECK_GE(level, 0.0); - CHECK_LE(level, 1.0); - CHECK_GT(level, prev_level); - prev_level = level; - - double db; - CHECK(volume_map_entry->GetDouble(kKeyDb, &db)); - CHECK_LE(db, 0.0); - if (level == 1.0) { - CHECK_EQ(db, 0.0); - } - - volume_map_.push_back({level, db}); - } - - if (volume_map_.empty()) { - LOG(FATAL) << "No entries in volume map."; - return; - } - - if (volume_map_[0].level > 0.0) { - volume_map_.insert(volume_map_.begin(), {0.0, kMinDbFS}); - } - - if (volume_map_.rbegin()->level < 1.0) { - volume_map_.push_back({1.0, 0.0}); - } - } - - float VolumeToDbFS(float volume) { - if (volume <= volume_map_[0].level) { - return volume_map_[0].db; - } - for (size_t i = 1; i < volume_map_.size(); ++i) { - if (volume < volume_map_[i].level) { - const float x_range = volume_map_[i].level - volume_map_[i - 1].level; - const float y_range = volume_map_[i].db - volume_map_[i - 1].db; - const float x_pos = volume - volume_map_[i - 1].level; - - return volume_map_[i - 1].db + x_pos * y_range / x_range; - } - } - return volume_map_[volume_map_.size() - 1].db; - } - - // static - float DbFSToVolume(float db) { - if (db <= volume_map_[0].db) { - return volume_map_[0].level; - } - for (size_t i = 1; i < volume_map_.size(); ++i) { - if (db < volume_map_[i].db) { - const float x_range = volume_map_[i].db - volume_map_[i - 1].db; - const float y_range = volume_map_[i].level - volume_map_[i - 1].level; - const float x_pos = db - volume_map_[i - 1].db; - - return volume_map_[i - 1].level + x_pos * y_range / x_range; - } - } - return volume_map_[volume_map_.size() - 1].level; - } - - private: - std::vector<LevelToDb> volume_map_; - - DISALLOW_COPY_AND_ASSIGN(VolumeMap); -}; - base::LazyInstance<VolumeMap>::Leaky g_volume_map = LAZY_INSTANCE_INITIALIZER; class VolumeControlInternal : public AlsaVolumeControl::Delegate { @@ -209,8 +100,8 @@ } } else { // If saved_volumes does not exist, use per device default if it exists. - auto cast_audio_config = DeserializeJsonFromFile( - base::FilePath(PostProcessingPipelineParser::GetFilePath())); + auto cast_audio_config = + DeserializeJsonFromFile(base::FilePath(kCastAudioJsonFilePath)); const base::DictionaryValue* cast_audio_dict; if (cast_audio_config && cast_audio_config->GetAsDictionary(&cast_audio_dict)) {
diff --git a/chromecast/media/cma/backend/alsa/volume_map.cc b/chromecast/media/cma/backend/alsa/volume_map.cc new file mode 100644 index 0000000..a8c3f34 --- /dev/null +++ b/chromecast/media/cma/backend/alsa/volume_map.cc
@@ -0,0 +1,123 @@ +// 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 "chromecast/media/cma/backend/alsa/volume_map.h" + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/values.h" +#include "chromecast/base/serializers.h" +#include "chromecast/media/cma/backend/alsa/cast_audio_json.h" + +namespace chromecast { +namespace media { + +namespace { +constexpr char kKeyVolumeMap[] = "volume_map"; +constexpr char kKeyLevel[] = "level"; +constexpr char kKeyDb[] = "db"; +constexpr float kMinDbFS = -120.0f; + +} // namespace + +VolumeMap::VolumeMap() { + auto cast_audio_config = + DeserializeJsonFromFile(base::FilePath(kCastAudioJsonFilePath)); + const base::DictionaryValue* cast_audio_dict; + if (!cast_audio_config || + !cast_audio_config->GetAsDictionary(&cast_audio_dict)) { + LOG(WARNING) << "No cast audio config found; using default volume map."; + UseDefaultVolumeMap(); + return; + } + + const base::ListValue* volume_map_list; + if (!cast_audio_dict->GetList(kKeyVolumeMap, &volume_map_list)) { + LOG(WARNING) << "No volume map found; using default volume map."; + UseDefaultVolumeMap(); + return; + } + + double prev_level = -1.0; + for (size_t i = 0; i < volume_map_list->GetSize(); ++i) { + const base::DictionaryValue* volume_map_entry; + CHECK(volume_map_list->GetDictionary(i, &volume_map_entry)); + + double level; + CHECK(volume_map_entry->GetDouble(kKeyLevel, &level)); + CHECK_GE(level, 0.0); + CHECK_LE(level, 1.0); + CHECK_GT(level, prev_level); + prev_level = level; + + double db; + CHECK(volume_map_entry->GetDouble(kKeyDb, &db)); + CHECK_LE(db, 0.0); + if (level == 1.0) { + CHECK_EQ(db, 0.0); + } + + volume_map_.push_back({level, db}); + } + + if (volume_map_.empty()) { + LOG(FATAL) << "No entries in volume map."; + return; + } + + if (volume_map_[0].level > 0.0) { + volume_map_.insert(volume_map_.begin(), {0.0, kMinDbFS}); + } + + if (volume_map_.rbegin()->level < 1.0) { + volume_map_.push_back({1.0, 0.0}); + } +} + +VolumeMap::~VolumeMap() = default; + +float VolumeMap::VolumeToDbFS(float volume) { + if (volume <= volume_map_[0].level) { + return volume_map_[0].db; + } + for (size_t i = 1; i < volume_map_.size(); ++i) { + if (volume < volume_map_[i].level) { + const float x_range = volume_map_[i].level - volume_map_[i - 1].level; + const float y_range = volume_map_[i].db - volume_map_[i - 1].db; + const float x_pos = volume - volume_map_[i - 1].level; + + return volume_map_[i - 1].db + x_pos * y_range / x_range; + } + } + return volume_map_[volume_map_.size() - 1].db; +} + +float VolumeMap::DbFSToVolume(float db) { + if (db <= volume_map_[0].db) { + return volume_map_[0].level; + } + for (size_t i = 1; i < volume_map_.size(); ++i) { + if (db < volume_map_[i].db) { + const float x_range = volume_map_[i].db - volume_map_[i - 1].db; + const float y_range = volume_map_[i].level - volume_map_[i - 1].level; + const float x_pos = db - volume_map_[i - 1].db; + + return volume_map_[i - 1].level + x_pos * y_range / x_range; + } + } + return volume_map_[volume_map_.size() - 1].level; +} + +// static +void VolumeMap::UseDefaultVolumeMap() { + volume_map_ = {{0.0f, kMinDbFS}, + {0.01f, -58.0f}, + {0.090909f, -48.0f}, + {0.818182f, -8.0f}, + {1.0f, 0.0f}}; +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/alsa/volume_map.h b/chromecast/media/cma/backend/alsa/volume_map.h new file mode 100644 index 0000000..493599dd --- /dev/null +++ b/chromecast/media/cma/backend/alsa/volume_map.h
@@ -0,0 +1,40 @@ +// 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 CHROMECAST_MEDIA_CMA_BACKEND_ALSA_VOLUME_MAP_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_ALSA_VOLUME_MAP_H_ + +#include <vector> + +#include "base/macros.h" + +namespace chromecast { +namespace media { + +class VolumeMap { + public: + VolumeMap(); + ~VolumeMap(); + + float VolumeToDbFS(float volume); + + float DbFSToVolume(float db); + + private: + struct LevelToDb { + float level; + float db; + }; + + void UseDefaultVolumeMap(); + + std::vector<LevelToDb> volume_map_; + + DISALLOW_COPY_AND_ASSIGN(VolumeMap); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_ALSA_VOLUME_MAP_H_
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc index 372c18b..8e6a01a3a 100644 --- a/chromecast/media/service/cast_renderer.cc +++ b/chromecast/media/service/cast_renderer.cc
@@ -101,7 +101,9 @@ AudioContentType content_type; if (audio_device_id_ == kAlarmAudioDeviceId) { content_type = AudioContentType::kAlarm; - } else if (audio_device_id_ == kTtsAudioDeviceId) { + } else if (audio_device_id_ == kTtsAudioDeviceId || + audio_device_id_ == + ::media::AudioDeviceDescription::kCommunicationsDeviceId) { content_type = AudioContentType::kCommunication; } else { content_type = AudioContentType::kMedia;
diff --git a/components/arc/test/fake_bluetooth_instance.h b/components/arc/test/fake_bluetooth_instance.h index 2121120..dd4bb9e1 100644 --- a/components/arc/test/fake_bluetooth_instance.h +++ b/components/arc/test/fake_bluetooth_instance.h
@@ -9,7 +9,6 @@ #include <vector> #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "components/arc/common/bluetooth.mojom.h" #include "mojo/public/cpp/bindings/binding.h"
diff --git a/components/autofill/content/renderer/test_password_generation_agent.h b/components/autofill/content/renderer/test_password_generation_agent.h index 11aef9d..6ab5509d 100644 --- a/components/autofill/content/renderer/test_password_generation_agent.h +++ b/components/autofill/content/renderer/test_password_generation_agent.h
@@ -8,7 +8,6 @@ #include <vector> #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "components/autofill/content/renderer/password_generation_agent.h" namespace autofill {
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index dd8e02b..310b22c 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -17,7 +17,6 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/metrics/field_trial.h" #include "base/metrics/metrics_hashes.h" #include "base/run_loop.h"
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc index 4e92e5c7..931f8b4 100644 --- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -14,7 +14,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/guid.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h"
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc index 261f63b..7d47212 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -13,7 +13,6 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/numerics/safe_conversions.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_data_model.h"
diff --git a/components/constrained_window/BUILD.gn b/components/constrained_window/BUILD.gn index a62c555..d4653d8b 100644 --- a/components/constrained_window/BUILD.gn +++ b/components/constrained_window/BUILD.gn
@@ -37,6 +37,7 @@ if (use_aura) { deps += [ "//ui/aura", + "//ui/compositor", "//ui/wm", ] }
diff --git a/components/constrained_window/DEPS b/components/constrained_window/DEPS index b4fd76f..01e4dfd93 100644 --- a/components/constrained_window/DEPS +++ b/components/constrained_window/DEPS
@@ -4,6 +4,7 @@ "+content/public/browser", "+ui/aura", "+ui/base", + "+ui/compositor", "+ui/display", "+ui/gfx", "+ui/views",
diff --git a/components/constrained_window/constrained_window_views.cc b/components/constrained_window/constrained_window_views.cc index 37de79c..18398d6 100644 --- a/components/constrained_window/constrained_window_views.cc +++ b/components/constrained_window/constrained_window_views.cc
@@ -24,6 +24,11 @@ #import "components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h" #endif +#if defined(USE_AURA) +#include "ui/aura/window.h" +#include "ui/compositor/dip_util.h" +#endif + using web_modal::ModalDialogHost; using web_modal::ModalDialogHostObserver; @@ -126,6 +131,19 @@ } widget->SetBounds(gfx::Rect(position, size)); + +#if defined(USE_AURA) + if (!widget->is_top_level()) { + // Toplevel windows are automatiacally snapped, but CHILD windows + // may not. If it's not toplevel, snap the widget's layer to pixel + // based on the parent toplevel window, which should be snapped. + gfx::NativeView window = widget->GetNativeView(); + views::Widget* toplevel = + views::Widget::GetTopLevelWidgetForNativeView(window->parent()); + ui::SnapLayerToPhysicalPixelBoundary(toplevel->GetLayer(), + widget->GetLayer()); + } +#endif } } // namespace
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc index b7aa07a..250a6658 100644 --- a/components/cronet/android/cronet_library_loader.cc +++ b/components/cronet/android/cronet_library_loader.cc
@@ -18,6 +18,7 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/metrics/statistics_recorder.h" +#include "base/task_scheduler/task_scheduler.h" #include "components/cronet/android/cronet_bidirectional_stream_adapter.h" #include "components/cronet/android/cronet_jni_registration.h" #include "components/cronet/android/cronet_upload_data_stream_adapter.h" @@ -67,6 +68,9 @@ bool NativeInit() { if (!base::android::OnJNIOnLoadInit()) return false; + if (!base::TaskScheduler::GetInstance()) + base::TaskScheduler::CreateAndStartWithDefaultParams("Cronet"); + url::Initialize(); // Initializes the statistics recorder system. This needs to be done before // emitting histograms to prevent memory leaks (crbug.com/707836). @@ -97,6 +101,9 @@ } void CronetOnUnLoad(JavaVM* jvm, void* reserved) { + if (base::TaskScheduler::GetInstance()) + base::TaskScheduler::GetInstance()->Shutdown(); + base::android::LibraryLoaderExitHook(); }
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 93820d83..0c9daaf 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -22,6 +22,7 @@ #include "net/cert/multi_threaded_cert_verifier.h" #include "net/dns/host_resolver.h" #include "net/dns/mapped_host_resolver.h" +#include "net/http/http_network_session.h" #include "net/http/http_server_properties.h" #include "net/nqe/network_quality_estimator_params.h" #include "net/quic/chromium/quic_utils_chromium.h" @@ -155,6 +156,7 @@ void URLRequestContextConfig::ParseAndSetExperimentalOptions( net::URLRequestContextBuilder* context_builder, + net::HttpNetworkSession::Params* session_params, net::NetLog* net_log, const scoped_refptr<base::SequencedTaskRunner>& file_task_runner) { if (experimental_options.empty()) @@ -189,6 +191,7 @@ effective_experimental_options = dict->CreateDeepCopy(); StaleHostResolver::StaleOptions stale_dns_options; std::string host_resolver_rules_string; + for (base::DictionaryValue::Iterator it(*dict.get()); !it.IsAtEnd(); it.Advance()) { if (it.key() == kQuicFieldTrialName) { @@ -202,8 +205,8 @@ std::string quic_connection_options; if (quic_args->GetString(kQuicConnectionOptions, &quic_connection_options)) { - context_builder->set_quic_connection_options( - net::ParseQuicConnectionOptions(quic_connection_options)); + session_params->quic_connection_options = + net::ParseQuicConnectionOptions(quic_connection_options); } // TODO(rtenneti): Delete this option after apps stop using it. @@ -211,63 +214,63 @@ bool quic_store_server_configs_in_properties = false; if (quic_args->GetBoolean(kQuicStoreServerConfigsInProperties, &quic_store_server_configs_in_properties)) { - context_builder->set_quic_max_server_configs_stored_in_properties( - net::kMaxQuicServersToPersist); + session_params->quic_max_server_configs_stored_in_properties = + net::kMaxQuicServersToPersist; } int quic_max_server_configs_stored_in_properties = 0; if (quic_args->GetInteger( kQuicMaxServerConfigsStoredInProperties, &quic_max_server_configs_stored_in_properties)) { - context_builder->set_quic_max_server_configs_stored_in_properties( - static_cast<size_t>(quic_max_server_configs_stored_in_properties)); + session_params->quic_max_server_configs_stored_in_properties = + static_cast<size_t>(quic_max_server_configs_stored_in_properties); } int quic_idle_connection_timeout_seconds = 0; if (quic_args->GetInteger(kQuicIdleConnectionTimeoutSeconds, &quic_idle_connection_timeout_seconds)) { - context_builder->set_quic_idle_connection_timeout_seconds( - quic_idle_connection_timeout_seconds); + session_params->quic_idle_connection_timeout_seconds = + quic_idle_connection_timeout_seconds; } bool quic_close_sessions_on_ip_change = false; if (quic_args->GetBoolean(kQuicCloseSessionsOnIpChange, &quic_close_sessions_on_ip_change)) { - context_builder->set_quic_close_sessions_on_ip_change( - quic_close_sessions_on_ip_change); + session_params->quic_close_sessions_on_ip_change = + quic_close_sessions_on_ip_change; } bool quic_migrate_sessions_on_network_change = false; if (quic_args->GetBoolean(kQuicMigrateSessionsOnNetworkChange, &quic_migrate_sessions_on_network_change)) { - context_builder->set_quic_migrate_sessions_on_network_change( - quic_migrate_sessions_on_network_change); + session_params->quic_migrate_sessions_on_network_change = + quic_migrate_sessions_on_network_change; } std::string quic_user_agent_id; if (quic_args->GetString(kQuicUserAgentId, &quic_user_agent_id)) { - context_builder->set_quic_user_agent_id(quic_user_agent_id); + session_params->quic_user_agent_id = quic_user_agent_id; } bool quic_migrate_sessions_early = false; if (quic_args->GetBoolean(kQuicMigrateSessionsEarly, &quic_migrate_sessions_early)) { - context_builder->set_quic_migrate_sessions_early( - quic_migrate_sessions_early); + session_params->quic_migrate_sessions_early = + quic_migrate_sessions_early; } bool quic_disable_bidirectional_streams = false; if (quic_args->GetBoolean(kQuicDisableBidirectionalStreams, &quic_disable_bidirectional_streams)) { - context_builder->set_quic_disable_bidirectional_streams( - quic_disable_bidirectional_streams); + session_params->quic_disable_bidirectional_streams = + quic_disable_bidirectional_streams; } bool quic_race_cert_verification = false; if (quic_args->GetBoolean(kQuicRaceCertVerification, &quic_race_cert_verification)) { - context_builder->set_quic_race_cert_verification( - quic_race_cert_verification); + session_params->quic_race_cert_verification = + quic_race_cert_verification; } } else if (it.key() == kAsyncDnsFieldTrialName) { @@ -434,12 +437,16 @@ context_builder->DisableHttpCache(); } context_builder->set_user_agent(user_agent); - context_builder->SetSpdyAndQuicEnabled(enable_spdy, enable_quic); context_builder->set_sdch_enabled(enable_sdch); + net::HttpNetworkSession::Params session_params; + session_params.enable_http2 = enable_spdy; + session_params.enable_quic = enable_quic; if (enable_quic) - context_builder->set_quic_user_agent_id(quic_user_agent_id); + session_params.quic_user_agent_id = quic_user_agent_id; - ParseAndSetExperimentalOptions(context_builder, net_log, file_task_runner); + ParseAndSetExperimentalOptions(context_builder, &session_params, net_log, + file_task_runner); + context_builder->set_http_network_session_params(session_params); std::unique_ptr<net::CertVerifier> cert_verifier; if (mock_cert_verifier) {
diff --git a/components/cronet/url_request_context_config.h b/components/cronet/url_request_context_config.h index a7fc179..2c11f360 100644 --- a/components/cronet/url_request_context_config.h +++ b/components/cronet/url_request_context_config.h
@@ -16,6 +16,7 @@ #include "base/values.h" #include "net/base/hash_value.h" #include "net/cert/cert_verifier.h" +#include "net/http/http_network_session.h" #include "net/nqe/effective_connection_type.h" namespace base { @@ -186,6 +187,7 @@ // the URLRequestContextConfig and URLRequestContextBuilder. void ParseAndSetExperimentalOptions( net::URLRequestContextBuilder* context_builder, + net::HttpNetworkSession::Params* session_params, net::NetLog* net_log, const scoped_refptr<base::SequencedTaskRunner>& file_task_runner); @@ -193,7 +195,8 @@ // experiments and their corresponding configuration options. The format // is a JSON object with the name of the experiment as the key, and the // configuration options as the value. An example: - // {"experiment1": {"option1": "option_value1", "option2": "option_value2", + // {"experiment1": {"option1": "option_value1", "option2": + // "option_value2", // ...}, "experiment2: {"option3", "option_value3", ...}, ...} const std::string experimental_options;
diff --git a/components/dom_distiller/content/renderer/distillability_agent.cc b/components/dom_distiller/content/renderer/distillability_agent.cc index 4bee7c3e..deea34d 100644 --- a/components/dom_distiller/content/renderer/distillability_agent.cc +++ b/components/dom_distiller/content/renderer/distillability_agent.cc
@@ -41,7 +41,8 @@ // The number of updates can be from 0 to 2. See the tests in // "distillable_page_utils_browsertest.cc". // Most heuristics types only require one update after parsing. -// Adaboost is the only one doing the second update, which is after loading. +// Adaboost-based heuristics are the only ones doing the second update, +// which is after loading. bool NeedToUpdate(bool is_loaded) { switch (GetDistillerHeuristicsType()) { case DistillerHeuristicsType::ALWAYS_TRUE: @@ -49,6 +50,7 @@ case DistillerHeuristicsType::OG_ARTICLE: return !is_loaded; case DistillerHeuristicsType::ADABOOST_MODEL: + case DistillerHeuristicsType::ALL_ARTICLES: return true; case DistillerHeuristicsType::NONE: default: @@ -58,7 +60,8 @@ // Returns whether this update is the last one for the page. bool IsLast(bool is_loaded) { - if (GetDistillerHeuristicsType() == DistillerHeuristicsType::ADABOOST_MODEL) + if (GetDistillerHeuristicsType() == DistillerHeuristicsType::ADABOOST_MODEL || + GetDistillerHeuristicsType() == DistillerHeuristicsType::ALL_ARTICLES) return is_loaded; return true; @@ -76,7 +79,8 @@ bool IsDistillablePageAdaboost(WebDocument& doc, const DistillablePageDetector* detector, const DistillablePageDetector* long_page, - bool is_last) { + bool is_last, + bool exclude_mobile) { WebDistillabilityFeatures features = doc.DistillabilityFeatures(); GURL parsed_url(doc.Url()); if (!parsed_url.is_valid()) { @@ -145,7 +149,7 @@ if (blacklisted) { return false; } - if (features.is_mobile_friendly) { + if (exclude_mobile && features.is_mobile_friendly) { return false; } return distillable && long_article; @@ -158,9 +162,13 @@ case DistillerHeuristicsType::OG_ARTICLE: return doc.DistillabilityFeatures().open_graph; case DistillerHeuristicsType::ADABOOST_MODEL: - return IsDistillablePageAdaboost(doc, - DistillablePageDetector::GetNewModel(), - DistillablePageDetector::GetLongPageModel(), is_last); + return IsDistillablePageAdaboost( + doc, DistillablePageDetector::GetNewModel(), + DistillablePageDetector::GetLongPageModel(), is_last, true); + case DistillerHeuristicsType::ALL_ARTICLES: + return IsDistillablePageAdaboost( + doc, DistillablePageDetector::GetNewModel(), + DistillablePageDetector::GetLongPageModel(), is_last, false); case DistillerHeuristicsType::NONE: default: return false;
diff --git a/components/dom_distiller/core/dom_distiller_switches.cc b/components/dom_distiller/core/dom_distiller_switches.cc index 70a90f1..0d3976b 100644 --- a/components/dom_distiller/core/dom_distiller_switches.cc +++ b/components/dom_distiller/core/dom_distiller_switches.cc
@@ -14,6 +14,7 @@ namespace reader_mode_heuristics { const char kAdaBoost[] = "adaboost"; +const char kAllArticles[] = "allarticles"; const char kOGArticle[] = "opengraph"; const char kAlwaysTrue[] = "alwaystrue"; const char kNone[] = "none";
diff --git a/components/dom_distiller/core/dom_distiller_switches.h b/components/dom_distiller/core/dom_distiller_switches.h index 91952d7b..8216477 100644 --- a/components/dom_distiller/core/dom_distiller_switches.h +++ b/components/dom_distiller/core/dom_distiller_switches.h
@@ -28,6 +28,7 @@ namespace reader_mode_heuristics { extern const char kAdaBoost[]; +extern const char kAllArticles[]; extern const char kOGArticle[]; extern const char kAlwaysTrue[]; extern const char kNone[];
diff --git a/components/dom_distiller/core/experiments.cc b/components/dom_distiller/core/experiments.cc index 900daec..ba011f5 100644 --- a/components/dom_distiller/core/experiments.cc +++ b/components/dom_distiller/core/experiments.cc
@@ -21,6 +21,9 @@ if (switch_value == switches::reader_mode_heuristics::kAdaBoost) { return DistillerHeuristicsType::ADABOOST_MODEL; } + if (switch_value == switches::reader_mode_heuristics::kAllArticles) { + return DistillerHeuristicsType::ALL_ARTICLES; + } if (switch_value == switches::reader_mode_heuristics::kOGArticle) { return DistillerHeuristicsType::OG_ARTICLE; } @@ -36,6 +39,10 @@ base::CompareCase::INSENSITIVE_ASCII)) { return DistillerHeuristicsType::ADABOOST_MODEL; } + if (base::StartsWith(group_name, "AllArticles", + base::CompareCase::INSENSITIVE_ASCII)) { + return DistillerHeuristicsType::ALL_ARTICLES; + } if (base::StartsWith(group_name, "OGArticle", base::CompareCase::INSENSITIVE_ASCII)) { return DistillerHeuristicsType::OG_ARTICLE;
diff --git a/components/dom_distiller/core/experiments.h b/components/dom_distiller/core/experiments.h index 16edfcb..80d02fa8 100644 --- a/components/dom_distiller/core/experiments.h +++ b/components/dom_distiller/core/experiments.h
@@ -6,14 +6,15 @@ #define COMPONENTS_DOM_DISTILLER_CORE_EXPERIMENTS_H_ namespace dom_distiller { - enum class DistillerHeuristicsType { - NONE, - OG_ARTICLE, - ADABOOST_MODEL, - ALWAYS_TRUE, - }; +enum class DistillerHeuristicsType { + NONE, + OG_ARTICLE, + ADABOOST_MODEL, + ALL_ARTICLES, + ALWAYS_TRUE, +}; - DistillerHeuristicsType GetDistillerHeuristicsType(); +DistillerHeuristicsType GetDistillerHeuristicsType(); } #endif // COMPONENTS_DOM_DISTILLER_CORE_EXPERIMENTS_H_
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc index 983c036..d7301cc 100644 --- a/components/exo/surface_unittest.cc +++ b/components/exo/surface_unittest.cc
@@ -6,7 +6,7 @@ #include "base/bind.h" #include "cc/output/compositor_frame.h" #include "cc/quads/texture_draw_quad.h" -#include "cc/surfaces/surface_manager.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_external_begin_frame_source.h" #include "components/exo/buffer.h" @@ -101,8 +101,10 @@ const cc::CompositorFrame& GetFrameFromSurface(Surface* surface) { cc::SurfaceId surface_id = surface->GetSurfaceId(); - cc::SurfaceManager* surface_manager = - aura::Env::GetInstance()->context_factory_private()->GetSurfaceManager(); + cc::SurfaceManager* surface_manager = aura::Env::GetInstance() + ->context_factory_private() + ->GetFrameSinkManager() + ->surface_manager(); const cc::CompositorFrame& frame = surface_manager->GetSurfaceForId(surface_id)->GetActiveFrame(); return frame;
diff --git a/components/ntp_tiles/webui/resources/ntp_tiles_internals.html b/components/ntp_tiles/webui/resources/ntp_tiles_internals.html index d97edb82..c407b726 100644 --- a/components/ntp_tiles/webui/resources/ntp_tiles_internals.html +++ b/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
@@ -116,7 +116,8 @@ <td class="value" jsdisplay="source == 1">SUGGESTIONS_SERVICE</td> <td class="value" jsdisplay="source == 2">POPULAR</td> <td class="value" jsdisplay="source == 3">WHITELIST</td> - <td class="value" jsdisplay="source > 3">???</td> + <td class="value" jsdisplay="source == 4">HOMEPAGE</td> + <td class="value" jsdisplay="source > 4">???</td> </tr> <tr> <td class="detail">URL</td>
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.cc b/components/offline_pages/content/background_loader/background_loader_contents.cc index 199c7d2c..3a08f96 100644 --- a/components/offline_pages/content/background_loader/background_loader_contents.cc +++ b/components/offline_pages/content/background_loader/background_loader_contents.cc
@@ -116,6 +116,25 @@ return false; // No permissions granted. } +void BackgroundLoaderContents::AdjustPreviewsStateForNavigation( + content::PreviewsState* previews_state) { + DCHECK(previews_state); + + // If previews are already disabled, do nothing. + if (*previews_state == content::PREVIEWS_OFF || + *previews_state == content::PREVIEWS_NO_TRANSFORM) { + return; + } + + if (*previews_state == content::PREVIEWS_UNSPECIFIED) { + *previews_state = content::PARTIAL_CONTENT_SAFE_PREVIEWS; + } else { + *previews_state &= content::PARTIAL_CONTENT_SAFE_PREVIEWS; + if (*previews_state == 0) + *previews_state = content::PREVIEWS_OFF; + } +} + BackgroundLoaderContents::BackgroundLoaderContents() : browser_context_(nullptr) { web_contents_.reset();
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.h b/components/offline_pages/content/background_loader/background_loader_contents.h index f4c9acd..ceb0641 100644 --- a/components/offline_pages/content/background_loader/background_loader_contents.h +++ b/components/offline_pages/content/background_loader/background_loader_contents.h
@@ -76,6 +76,9 @@ const GURL& security_origin, content::MediaStreamType type) override; + void AdjustPreviewsStateForNavigation( + content::PreviewsState* previews_state) override; + private: friend class BackgroundLoaderContentsTest; friend class BackgroundLoaderContentsStub;
diff --git a/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc b/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc index 3cfae2c..ddfe43a 100644 --- a/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc +++ b/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc
@@ -146,4 +146,34 @@ content::MediaStreamType::MEDIA_TAB_VIDEO_CAPTURE /* type */)); } +TEST_F(BackgroundLoaderContentsTest, AdjustPreviewsState) { + content::PreviewsState previews_state; + + // If the state starts out as off or disabled, it should stay that way. + previews_state = content::PREVIEWS_OFF; + contents()->AdjustPreviewsStateForNavigation(&previews_state); + EXPECT_EQ(previews_state, content::PREVIEWS_OFF); + previews_state = content::PREVIEWS_NO_TRANSFORM; + contents()->AdjustPreviewsStateForNavigation(&previews_state); + EXPECT_EQ(previews_state, content::PREVIEWS_NO_TRANSFORM); + + // If the state starts out as a state unfriendly to offlining, we should + // and out the unfriendly previews. + previews_state = content::SERVER_LOFI_ON | content::CLIENT_LOFI_ON; + contents()->AdjustPreviewsStateForNavigation(&previews_state); + EXPECT_EQ(previews_state, content::SERVER_LOFI_ON); + + // If the state starts out as offlining friendly previews, we should preserve + // them. + previews_state = content::PARTIAL_CONTENT_SAFE_PREVIEWS; + contents()->AdjustPreviewsStateForNavigation(&previews_state); + EXPECT_EQ(previews_state, content::PARTIAL_CONTENT_SAFE_PREVIEWS); + + // If there are only offlining unfriendly previews, they should all get turned + // off. + previews_state = content::CLIENT_LOFI_ON; + contents()->AdjustPreviewsStateForNavigation(&previews_state); + EXPECT_EQ(previews_state, content::PREVIEWS_OFF); +} + } // namespace background_loader
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index d251027..ef525db 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -9,6 +9,7 @@ #include <string> #include <utility> +#include "base/feature_list.h" #include "base/format_macros.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -204,6 +205,7 @@ stop_timer_duration_(OmniboxFieldTrial::StopTimerFieldTrialDuration()), done_(true), in_start_(false), + search_service_worker_signal_sent_(false), template_url_service_(provider_client_->GetTemplateURLService()) { provider_types &= ~OmniboxFieldTrial::GetDisabledProviderTypes(); if (provider_types & AutocompleteProvider::TYPE_BOOKMARK) @@ -341,6 +343,24 @@ // need the edit model to update the display. UpdateResult(false, true); + // If the input looks like a query, send a signal predicting that the user is + // going to issue a search (either to the default search engine or to a + // keyword search engine, as indicated by the destination_url). This allows + // any associated service worker to start up early and reduce the latency of a + // resulting search. However, to avoid a potentially expensive operation, we + // only do this once per session. Additionally, a default match is expected to + // be available at this point but we check anyway to guard against an invalid + // dereference. + if (base::FeatureList::IsEnabled( + omnibox::kSpeculativeServiceWorkerStartOnQueryInput) && + (input.type() == metrics::OmniboxInputType::QUERY) && + !search_service_worker_signal_sent_ && + (result_.default_match() != result_.end())) { + search_service_worker_signal_sent_ = true; + provider_client_->StartServiceWorker( + result_.default_match()->destination_url); + } + if (!done_) { StartExpireTimer(); StartStopTimer(); @@ -400,6 +420,8 @@ } void AutocompleteController::ResetSession() { + search_service_worker_signal_sent_ = false; + for (Providers::const_iterator i(providers_.begin()); i != providers_.end(); ++i) (*i)->ResetSession();
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h index 75934052..52c13fd 100644 --- a/components/omnibox/browser/autocomplete_controller.h +++ b/components/omnibox/browser/autocomplete_controller.h
@@ -248,6 +248,11 @@ // notifications until Start() has been invoked on all providers. bool in_start_; + // True if the signal predicting a likely search has already been sent to the + // service worker context during the current input session. False on + // controller creation and after |ResetSession| is called. + bool search_service_worker_signal_sent_; + TemplateURLService* template_url_service_; DISALLOW_COPY_AND_ASSIGN(AutocompleteController);
diff --git a/components/omnibox/browser/autocomplete_provider_client.h b/components/omnibox/browser/autocomplete_provider_client.h index 63e818b..16b7798 100644 --- a/components/omnibox/browser/autocomplete_provider_client.h +++ b/components/omnibox/browser/autocomplete_provider_client.h
@@ -110,6 +110,12 @@ virtual void PrefetchImage(const GURL& url) = 0; + // Sends a hint to the service worker context that navigation to + // |desination_url| is likely. On platforms where this is supported, the + // service worker lookup can be expensive so this method should only be + // called once per input session. + virtual void StartServiceWorker(const GURL& destination_url) {} + // Called by |controller| when its results have changed and all providers are // done processing the autocomplete request. At the //chrome level, this // callback results in firing the
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index 7a8e739..4868f41 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -149,6 +149,7 @@ if (MaybePrependKeyword(display_text).empty()) { base::AutoReset<bool> tmp(&in_revert_, true); view_->RevertAll(); + view_->SelectAll(true); } else { InternalSetUserText(display_text); } @@ -369,8 +370,13 @@ keyword_.clear(); is_keyword_hint_ = false; has_temporary_text_ = false; + size_t start, end; + view_->GetSelectionBounds(&start, &end); + // First home the cursor, so view of text is scrolled to left, then correct + // it. |SetCaretPos()| doesn't scroll the text, so doing that first wouldn't + // accomplish anything. view_->SetWindowTextAndCaretPos(permanent_text_, 0, false, true); - view_->SelectAll(true); + view_->SetCaretPos(std::min(permanent_text_.length(), start)); client_->OnRevert(); } @@ -653,6 +659,9 @@ SEARCH_ENGINE_MAX); } + // Get the current text before we call RevertAll() which will clear it. + base::string16 current_text = view_->GetText(); + if (disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB) { base::AutoReset<bool> tmp(&in_revert_, true); view_->RevertAll(); // Revert the box to its unedited state. @@ -928,6 +937,7 @@ // for ease of replacement, and matches other browsers. bool user_input_was_in_progress = user_input_in_progress_; view_->RevertAll(); + view_->SelectAll(true); // If the user was in the midst of editing, don't cancel any underlying page // load. This doesn't match IE or Firefox, but seems more correct. Note that
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 6357182..18b68d8 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -132,6 +132,13 @@ const base::Feature kUIExperimentVerticalMargin{ "OmniboxUIExperimentVerticalMargin", base::FEATURE_DISABLED_BY_DEFAULT}; +// Feature used to enable speculatively starting a service worker associated +// with the destination of the default match when the user's input looks like a +// query. +const base::Feature kSpeculativeServiceWorkerStartOnQueryInput{ + "OmniboxSpeculativeServiceWorkerStartOnQueryInput", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace omnibox namespace {
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index 43a8c60a..ded0f0c 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -42,6 +42,7 @@ extern const base::Feature kUIExperimentNarrowDropdown; extern const base::Feature kUIExperimentVerticalLayout; extern const base::Feature kUIExperimentVerticalMargin; +extern const base::Feature kSpeculativeServiceWorkerStartOnQueryInput; } // The set of parameters customizing the HUP scoring.
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentManifestDownloader.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentManifestDownloader.java index adcb3d29..95029f4 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentManifestDownloader.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentManifestDownloader.java
@@ -4,6 +4,8 @@ package org.chromium.components.payments; +import org.chromium.base.ThreadUtils; +import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.content_public.browser.WebContents; @@ -12,7 +14,7 @@ /** * See comment in: - * components/payments/content/android/payment_manifest_downloader.h + * components/payments/content/payment_manifest_downloader.h */ @JNINamespace("payments") public class PaymentManifestDownloader { @@ -39,16 +41,32 @@ void onManifestDownloadFailure(); } - private final WebContents mWebContents; + private long mNativeObject; /** - * Builds the downloader. + * Initializes the native downloader. * - * @param webContents The web contents to use as the context for the download. If this goes - * away, the download is cancelled. + * @param webContents The web contents to use as the context for the downloads. If this goes + * away, pending downloads are cancelled. */ - public PaymentManifestDownloader(WebContents webContents) { - mWebContents = webContents; + public void initialize(WebContents webContents) { + ThreadUtils.assertOnUiThread(); + assert mNativeObject == 0; + mNativeObject = nativeInit(webContents); + } + + /** @return Whether the native downloader is initialized. */ + public boolean isInitialized() { + ThreadUtils.assertOnUiThread(); + return mNativeObject != 0; + } + + /** Allows HTTP URLs. Should be used for testing only. */ + @VisibleForTesting + public void allowHttpForTest() { + ThreadUtils.assertOnUiThread(); + assert mNativeObject != 0; + nativeAllowHttpForTest(mNativeObject); } /** @@ -58,17 +76,29 @@ * @param callback The callback to invoke when finished downloading. */ public void downloadPaymentMethodManifest(URI methodName, ManifestDownloadCallback callback) { - nativeDownloadPaymentMethodManifest(mWebContents, methodName, callback); + ThreadUtils.assertOnUiThread(); + assert mNativeObject != 0; + nativeDownloadPaymentMethodManifest(mNativeObject, methodName, callback); } /** * Downloads the web app manifest file asynchronously. * - * @param webAppmanifestUri The web app manifest URI with HTTPS scheme. + * @param webAppManifestUri The web app manifest URI with HTTPS scheme. * @param callback The callback to invoke when finished downloading. */ public void downloadWebAppManifest(URI webAppManifestUri, ManifestDownloadCallback callback) { - nativeDownloadWebAppManifest(mWebContents, webAppManifestUri, callback); + ThreadUtils.assertOnUiThread(); + assert mNativeObject != 0; + nativeDownloadWebAppManifest(mNativeObject, webAppManifestUri, callback); + } + + /** Destroys the native downloader. */ + public void destroy() { + ThreadUtils.assertOnUiThread(); + assert mNativeObject != 0; + nativeDestroy(mNativeObject); + mNativeObject = 0; } @CalledByNative @@ -76,8 +106,12 @@ return methodName.toString(); } - private static native void nativeDownloadPaymentMethodManifest( - WebContents webContents, URI methodName, ManifestDownloadCallback callback); - private static native void nativeDownloadWebAppManifest( - WebContents webContents, URI webAppManifestUri, ManifestDownloadCallback callback); + private static native long nativeInit(WebContents webContents); + private native void nativeAllowHttpForTest(long nativePaymentManifestDownloaderAndroid); + private native void nativeDownloadPaymentMethodManifest( + long nativePaymentManifestDownloaderAndroid, URI methodName, + ManifestDownloadCallback callback); + private native void nativeDownloadWebAppManifest(long nativePaymentManifestDownloaderAndroid, + URI webAppManifestUri, ManifestDownloadCallback callback); + private native void nativeDestroy(long nativePaymentManifestDownloaderAndroid); }
diff --git a/components/payments/content/android/payment_manifest_downloader_android.cc b/components/payments/content/android/payment_manifest_downloader_android.cc index b7931b41..d6503d9 100644 --- a/components/payments/content/android/payment_manifest_downloader_android.cc +++ b/components/payments/content/android/payment_manifest_downloader_android.cc
@@ -2,133 +2,116 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <memory> -#include <utility> +#include "components/payments/content/android/payment_manifest_downloader_android.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" -#include "base/logging.h" #include "base/memory/ptr_util.h" -#include "components/payments/content/payment_manifest_downloader.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "jni/PaymentManifestDownloader_jni.h" #include "net/url_request/url_request_context_getter.h" #include "url/gurl.h" -#include "url/url_constants.h" namespace payments { namespace { -class SelfDeletingDownloadDelegate - : public PaymentManifestDownloader::Delegate { +class DownloadCallback { public: - explicit SelfDeletingDownloadDelegate( - const base::android::JavaParamRef<jobject>& jcallback) - : jcallback_(jcallback), is_downloading_payment_method_manifest_(true) {} + DownloadCallback(const base::android::JavaParamRef<jobject>& jcallback) + : jcallback_(jcallback) {} - void set_downloader(std::unique_ptr<PaymentManifestDownloader> downloader) { - downloader_ = std::move(downloader); - } + ~DownloadCallback() {} - void DownloadPaymentMethodManifest() { - is_downloading_payment_method_manifest_ = true; - downloader_->DownloadPaymentMethodManifest(); - } - - void DownloadWebAppManifest() { - is_downloading_payment_method_manifest_ = false; - downloader_->DownloadWebAppManifest(); - } - - // PaymentManifestDownloader::Delegate - void OnManifestDownloadSuccess(const std::string& content) override { + void OnPaymentMethodManifestDownload(const std::string& content) { JNIEnv* env = base::android::AttachCurrentThread(); - if (is_downloading_payment_method_manifest_) { + + if (content.empty()) { + Java_ManifestDownloadCallback_onManifestDownloadFailure(env, jcallback_); + } else { Java_ManifestDownloadCallback_onPaymentMethodManifestDownloadSuccess( env, jcallback_, base::android::ConvertUTF8ToJavaString(env, content)); + } + } + + void OnWebAppManifestDownload(const std::string& content) { + JNIEnv* env = base::android::AttachCurrentThread(); + + if (content.empty()) { + Java_ManifestDownloadCallback_onManifestDownloadFailure(env, jcallback_); } else { Java_ManifestDownloadCallback_onWebAppManifestDownloadSuccess( env, jcallback_, base::android::ConvertUTF8ToJavaString(env, content)); } - delete this; - } - - // PaymentManifestDownloader::Delegate - void OnManifestDownloadFailure() override { - Java_ManifestDownloadCallback_onManifestDownloadFailure( - base::android::AttachCurrentThread(), jcallback_); - delete this; } private: - ~SelfDeletingDownloadDelegate() override {} - base::android::ScopedJavaGlobalRef<jobject> jcallback_; - bool is_downloading_payment_method_manifest_; - std::unique_ptr<PaymentManifestDownloader> downloader_; - DISALLOW_COPY_AND_ASSIGN(SelfDeletingDownloadDelegate); + DISALLOW_COPY_AND_ASSIGN(DownloadCallback); }; -SelfDeletingDownloadDelegate* BuildSelfDeletingDownloadDelegate( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jweb_contents, - const base::android::JavaParamRef<jobject>& juri, - const base::android::JavaParamRef<jobject>& jcallback) { - SelfDeletingDownloadDelegate* delegate = - new SelfDeletingDownloadDelegate(jcallback); - - content::WebContents* web_contents = - content::WebContents::FromJavaWebContents(jweb_contents); - if (!web_contents) { - delegate->OnManifestDownloadFailure(); - return nullptr; - } - - GURL url(base::android::ConvertJavaStringToUTF8( - env, Java_PaymentManifestDownloader_getUriString(env, juri))); - DCHECK(url.is_valid()); - DCHECK(url.SchemeIs(url::kHttpsScheme)); - - std::unique_ptr<PaymentManifestDownloader> downloader = - base::MakeUnique<PaymentManifestDownloader>( - content::BrowserContext::GetDefaultStoragePartition( - web_contents->GetBrowserContext()) - ->GetURLRequestContext(), - url, delegate); - delegate->set_downloader(std::move(downloader)); - - return delegate; -} - } // namespace -void DownloadPaymentMethodManifest( +PaymentManifestDownloaderAndroid::PaymentManifestDownloaderAndroid( + const scoped_refptr<net::URLRequestContextGetter>& context) + : downloader_(context) {} + +PaymentManifestDownloaderAndroid::~PaymentManifestDownloaderAndroid() {} + +void PaymentManifestDownloaderAndroid::DownloadPaymentMethodManifest( JNIEnv* env, - const base::android::JavaParamRef<jclass>& jcaller, - const base::android::JavaParamRef<jobject>& jweb_contents, - const base::android::JavaParamRef<jobject>& jmethod_name, + const base::android::JavaParamRef<jobject>& jcaller, + const base::android::JavaParamRef<jobject>& juri, const base::android::JavaParamRef<jobject>& jcallback) { - SelfDeletingDownloadDelegate* delegate = BuildSelfDeletingDownloadDelegate( - env, jweb_contents, jmethod_name, jcallback); - if (delegate) - delegate->DownloadPaymentMethodManifest(); + downloader_.DownloadPaymentMethodManifest( + GURL(base::android::ConvertJavaStringToUTF8( + env, Java_PaymentManifestDownloader_getUriString(env, juri))), + base::BindOnce(&DownloadCallback::OnPaymentMethodManifestDownload, + base::MakeUnique<DownloadCallback>(jcallback))); } -void DownloadWebAppManifest( +void PaymentManifestDownloaderAndroid::DownloadWebAppManifest( JNIEnv* env, - const base::android::JavaParamRef<jclass>& jcaller, - const base::android::JavaParamRef<jobject>& jweb_contents, - const base::android::JavaParamRef<jobject>& jweb_app_manifest_uri, + const base::android::JavaParamRef<jobject>& jcaller, + const base::android::JavaParamRef<jobject>& juri, const base::android::JavaParamRef<jobject>& jcallback) { - SelfDeletingDownloadDelegate* delegate = BuildSelfDeletingDownloadDelegate( - env, jweb_contents, jweb_app_manifest_uri, jcallback); - if (delegate) - delegate->DownloadWebAppManifest(); + downloader_.DownloadWebAppManifest( + GURL(base::android::ConvertJavaStringToUTF8( + env, Java_PaymentManifestDownloader_getUriString(env, juri))), + base::BindOnce(&DownloadCallback::OnWebAppManifestDownload, + base::MakeUnique<DownloadCallback>(jcallback))); +} + +void PaymentManifestDownloaderAndroid::Destroy( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller) { + delete this; +} + +void PaymentManifestDownloaderAndroid::AllowHttpForTest( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller) { + downloader_.AllowHttpForTest(); +} + +// Static free function declared and called directly from java. +// Caller owns the result. Returns 0 on error. +static jlong Init(JNIEnv* env, + const base::android::JavaParamRef<jclass>& jcaller, + const base::android::JavaParamRef<jobject>& jweb_contents) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + if (!web_contents) + return 0; + + return reinterpret_cast<jlong>(new PaymentManifestDownloaderAndroid( + content::BrowserContext::GetDefaultStoragePartition( + web_contents->GetBrowserContext()) + ->GetURLRequestContext())); } } // namespace payments
diff --git a/components/payments/content/android/payment_manifest_downloader_android.h b/components/payments/content/android/payment_manifest_downloader_android.h new file mode 100644 index 0000000..cfbb4cb --- /dev/null +++ b/components/payments/content/android/payment_manifest_downloader_android.h
@@ -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. + +#ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_MANIFEST_DOWNLOADER_ANDROID_H_ +#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_MANIFEST_DOWNLOADER_ANDROID_H_ + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "components/payments/content/payment_manifest_downloader.h" + +namespace net { +class URLRequestContextGetter; +} + +namespace payments { + +// Android wrapper for the payment manifest downloader. +class PaymentManifestDownloaderAndroid { + public: + explicit PaymentManifestDownloaderAndroid( + const scoped_refptr<net::URLRequestContextGetter>& context); + ~PaymentManifestDownloaderAndroid(); + + void DownloadPaymentMethodManifest( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + const base::android::JavaParamRef<jobject>& juri, + const base::android::JavaParamRef<jobject>& jcallback); + + void DownloadWebAppManifest( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + const base::android::JavaParamRef<jobject>& juri, + const base::android::JavaParamRef<jobject>& jcallback); + + // Deletes this object. + void Destroy(JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller); + + // Allows HTTP URLs. Should be used for testing only. + void AllowHttpForTest(JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller); + + private: + PaymentManifestDownloader downloader_; + + DISALLOW_COPY_AND_ASSIGN(PaymentManifestDownloaderAndroid); +}; + +} // namespace payments + +#endif // COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_MANIFEST_DOWNLOADER_ANDROID_H_
diff --git a/components/payments/content/android/payment_manifest_parser_android.cc b/components/payments/content/android/payment_manifest_parser_android.cc index 2760790..a740ecb 100644 --- a/components/payments/content/android/payment_manifest_parser_android.cc +++ b/components/payments/content/android/payment_manifest_parser_android.cc
@@ -5,9 +5,11 @@ #include "components/payments/content/android/payment_manifest_parser_android.h" #include <stddef.h> +#include <vector> #include "base/android/jni_array.h" #include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" #include "base/bind.h" #include "base/logging.h" #include "base/memory/ptr_util.h"
diff --git a/components/payments/content/android/payment_manifest_parser_android.h b/components/payments/content/android/payment_manifest_parser_android.h index 5457f81d..65fc725 100644 --- a/components/payments/content/android/payment_manifest_parser_android.h +++ b/components/payments/content/android/payment_manifest_parser_android.h
@@ -7,11 +7,7 @@ #include <jni.h> -#include <memory> -#include <vector> - #include "base/android/jni_android.h" -#include "base/android/scoped_java_ref.h" #include "base/macros.h" #include "components/payments/content/payment_manifest_parser_host.h"
diff --git a/components/payments/content/payment_manifest_downloader.cc b/components/payments/content/payment_manifest_downloader.cc index 15a8783..63c4e07 100644 --- a/components/payments/content/payment_manifest_downloader.cc +++ b/components/payments/content/payment_manifest_downloader.cc
@@ -10,6 +10,8 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "base/strings/string_split.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/link_header_util/link_header_util.h" @@ -24,44 +26,110 @@ namespace payments { namespace { -bool IsValidManifestUrl(const GURL& url) { - return url.is_valid() && url.SchemeIs(url::kHttpsScheme); +GURL ParseResponseHeader(const net::URLFetcher* source) { + if (source->GetResponseCode() != net::HTTP_OK && + source->GetResponseCode() != net::HTTP_NO_CONTENT) { + return GURL(); + } + + net::HttpResponseHeaders* headers = source->GetResponseHeaders(); + if (!headers) + return GURL(); + + std::string link_header; + headers->GetNormalizedHeader("link", &link_header); + if (link_header.empty()) + return GURL(); + + std::string payment_method_manifest_url; + std::unordered_map<std::string, base::Optional<std::string>> params; + for (const auto& value : link_header_util::SplitLinkHeader(link_header)) { + if (!link_header_util::ParseLinkHeaderValue( + value.first, value.second, &payment_method_manifest_url, ¶ms)) { + continue; + } + + auto rel = params.find("rel"); + if (rel == params.end()) + continue; + + std::vector<std::string> rel_parts = + base::SplitString(rel->second.value_or(""), HTTP_LWS, + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (base::ContainsValue(rel_parts, "payment-method-manifest")) + return source->GetOriginalURL().Resolve(payment_method_manifest_url); + } + + return GURL(); +} + +std::string ParseResponseContent(const net::URLFetcher* source) { + std::string content; + if (source->GetResponseCode() != net::HTTP_OK) + return content; + + bool success = source->GetResponseAsString(&content); + DCHECK(success); // Whether the fetcher was set to store result as string. + + return content; } } // namespace PaymentManifestDownloader::PaymentManifestDownloader( - const scoped_refptr<net::URLRequestContextGetter>& context, - const GURL& url, - Delegate* delegate) - : context_(context), - url_(url), - delegate_(delegate), - is_downloading_http_link_header_(true) { - DCHECK(IsValidManifestUrl(url_)); -} + const scoped_refptr<net::URLRequestContextGetter>& context) + : context_(context), allow_http_for_test_(false) {} PaymentManifestDownloader::~PaymentManifestDownloader() {} -void PaymentManifestDownloader::DownloadPaymentMethodManifest() { - DCHECK(!fetcher_); - is_downloading_http_link_header_ = true; - InitiateDownload(url_, net::URLFetcher::HEAD); +void PaymentManifestDownloader::DownloadPaymentMethodManifest( + const GURL& url, + DownloadCallback callback) { + DCHECK(IsValidManifestUrl(url)); + InitiateDownload(url, net::URLFetcher::HEAD, std::move(callback)); } -void PaymentManifestDownloader::DownloadWebAppManifest() { - DCHECK(!fetcher_); - is_downloading_http_link_header_ = false; - InitiateDownload(url_, net::URLFetcher::GET); +void PaymentManifestDownloader::DownloadWebAppManifest( + const GURL& url, + DownloadCallback callback) { + DCHECK(IsValidManifestUrl(url)); + InitiateDownload(url, net::URLFetcher::GET, std::move(callback)); +} + +void PaymentManifestDownloader::AllowHttpForTest() { + allow_http_for_test_ = true; +} + +PaymentManifestDownloader::Download::Download() {} + +PaymentManifestDownloader::Download::~Download() {} + +void PaymentManifestDownloader::OnURLFetchComplete( + const net::URLFetcher* source) { + auto download_it = downloads_.find(source); + DCHECK(download_it != downloads_.end()); + + std::unique_ptr<Download> download = std::move(download_it->second); + downloads_.erase(download_it); + + if (download->request_type == net::URLFetcher::HEAD) { + GURL url = ParseResponseHeader(source); + if (IsValidManifestUrl(url)) { + InitiateDownload(url, net::URLFetcher::GET, + std::move(download->callback)); + } else { + std::move(download->callback).Run(std::string()); + } + } else { + std::move(download->callback).Run(ParseResponseContent(source)); + } } void PaymentManifestDownloader::InitiateDownload( const GURL& url, - net::URLFetcher::RequestType request_type) { - if (!IsValidManifestUrl(url)) { - delegate_->OnManifestDownloadFailure(); - return; - } + net::URLFetcher::RequestType request_type, + DownloadCallback callback) { + DCHECK(IsValidManifestUrl(url)); net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("payment_manifest_downloader", R"( @@ -83,69 +151,31 @@ "disable all payment apps to stop this feature." policy_exception_justification: "Not implemented." })"); - fetcher_ = net::URLFetcher::Create(0 /* id */, url, request_type, this, - traffic_annotation); + std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create( + 0 /* id */, url, request_type, this, traffic_annotation); data_use_measurement::DataUseUserData::AttachToFetcher( - fetcher_.get(), data_use_measurement::DataUseUserData::PAYMENTS); - fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SAVE_COOKIES); - fetcher_->SetStopOnRedirect(true); - fetcher_->SetRequestContext(context_.get()); - fetcher_->Start(); + fetcher.get(), data_use_measurement::DataUseUserData::PAYMENTS); + fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES); + fetcher->SetStopOnRedirect(true); + fetcher->SetRequestContext(context_.get()); + fetcher->Start(); + + auto download = base::MakeUnique<Download>(); + download->request_type = request_type; + download->fetcher = std::move(fetcher); + download->callback = std::move(callback); + + const net::URLFetcher* identifier = download->fetcher.get(); + auto insert_result = + downloads_.insert(std::make_pair(identifier, std::move(download))); + DCHECK(insert_result.second); // Whether the insert has succeeded. } -void PaymentManifestDownloader::OnURLFetchComplete( - const net::URLFetcher* source) { - if (source->GetResponseCode() != net::HTTP_OK) { - delegate_->OnManifestDownloadFailure(); - return; - } - - if (is_downloading_http_link_header_) { - is_downloading_http_link_header_ = false; - - net::HttpResponseHeaders* headers = source->GetResponseHeaders(); - if (!headers) { - delegate_->OnManifestDownloadFailure(); - return; - } - - std::string link_header; - headers->GetNormalizedHeader("link", &link_header); - if (!link_header.empty()) { - std::string payment_method_manifest_url; - std::unordered_map<std::string, base::Optional<std::string>> params; - for (const auto& value : link_header_util::SplitLinkHeader(link_header)) { - if (!link_header_util::ParseLinkHeaderValue( - value.first, value.second, &payment_method_manifest_url, - ¶ms)) { - continue; - } - - auto rel = params.find("rel"); - if (rel == params.end()) - continue; - - std::vector<std::string> rel_parts = - base::SplitString(rel->second.value_or(""), HTTP_LWS, - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - if (std::find(rel_parts.begin(), rel_parts.end(), - "payment-method-manifest") != rel_parts.end()) { - InitiateDownload(url_.Resolve(payment_method_manifest_url), - net::URLFetcher::GET); - return; - } - } - } - } else { - std::string content; - if (source->GetResponseAsString(&content) && !content.empty()) { - delegate_->OnManifestDownloadSuccess(content); - return; - } - } - - delegate_->OnManifestDownloadFailure(); +bool PaymentManifestDownloader::IsValidManifestUrl(const GURL& url) { + return url.is_valid() && + (url.SchemeIs(url::kHttpsScheme) || + (url.SchemeIs(url::kHttpScheme) && allow_http_for_test_)); } } // namespace payments
diff --git a/components/payments/content/payment_manifest_downloader.h b/components/payments/content/payment_manifest_downloader.h index ac1a95b..6ef80d3b 100644 --- a/components/payments/content/payment_manifest_downloader.h +++ b/components/payments/content/payment_manifest_downloader.h
@@ -5,9 +5,11 @@ #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_MANIFEST_DOWNLOADER_H_ #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_MANIFEST_DOWNLOADER_H_ +#include <map> #include <memory> #include <string> +#include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "net/url_request/url_fetcher.h" @@ -28,34 +30,23 @@ // HTTP response codes are 200. class PaymentManifestDownloader : public net::URLFetcherDelegate { public: - // The interface for receiving the result of downloading a manifest. - class Delegate { - public: - // Called when a manifest has been successfully downloaded. - virtual void OnManifestDownloadSuccess(const std::string& content) = 0; + // Called on completed download of a manifest. Download failure results in + // empty contents. Failure to download the manifest can happen because of the + // following reasons: + // - HTTP response code is not 200. (204 is also allowed for HEAD request.) + // - HTTP GET on the manifest URL returns empty content. + // + // In the case of a payment method manifest download, can also be called + // when: + // - HTTP response headers are absent. + // - HTTP response headers do not contain Link headers. + // - Link header does not contain rel="payment-method-manifest". + // - Link header does not contain a valid URL. + using DownloadCallback = base::OnceCallback<void(const std::string&)>; - // Called when failed to download the manifest for any reason: - // - HTTP response code is not 200. - // - HTTP GET on the manifest URL returns empty content. - // - // In the case of a payment method manifest download, can also be called - // when: - // - HTTP response headers are absent. - // - HTTP response headers do not contain Link headers. - // - Link header does not contain rel="payment-method-manifest". - // - Link header does not contain a valid URL. - virtual void OnManifestDownloadFailure() = 0; - - protected: - virtual ~Delegate() {} - }; - - // |delegate| should not be null and must outlive this object. |url| should be - // a valid URL with HTTPS scheme. - PaymentManifestDownloader( - const scoped_refptr<net::URLRequestContextGetter>& context, - const GURL& url, - Delegate* delegate); + // |delegate| should not be null and must outlive this object. + explicit PaymentManifestDownloader( + const scoped_refptr<net::URLRequestContextGetter>& context); ~PaymentManifestDownloader() override; @@ -76,28 +67,48 @@ // The absolute location must use HTTPS scheme. // // 2) GET request for the payment method manifest file. - void DownloadPaymentMethodManifest(); + // + // |url| should be a valid URL with HTTPS scheme. + void DownloadPaymentMethodManifest(const GURL& url, + DownloadCallback callback); // Download a web app manifest via a single HTTP request: // // 1) GET request for the payment method name. - void DownloadWebAppManifest(); + // + // |url| should be a valid URL with HTTPS scheme. + void DownloadWebAppManifest(const GURL& url, DownloadCallback callback); + + // Allows HTTP URLs. Should be used only for testing. + void AllowHttpForTest(); private: - void InitiateDownload(const GURL& url, - net::URLFetcher::RequestType request_type); + // Information about an ongoing download request. + struct Download { + Download(); + ~Download(); + + net::URLFetcher::RequestType request_type; + std::unique_ptr<net::URLFetcher> fetcher; + DownloadCallback callback; + }; // net::URLFetcherDelegate void OnURLFetchComplete(const net::URLFetcher* source) override; + void InitiateDownload(const GURL& url, + net::URLFetcher::RequestType request_type, + DownloadCallback callback); + bool IsValidManifestUrl(const GURL& url); + scoped_refptr<net::URLRequestContextGetter> context_; - const GURL url_; + bool allow_http_for_test_; - // Non-owned. Never null. Outlives this object. - Delegate* delegate_; - - bool is_downloading_http_link_header_; - std::unique_ptr<net::URLFetcher> fetcher_; + // Downloads are identified by net::URLFetcher pointers, because that's the + // only unique piece of information that OnURLFetchComplete() receives. Can't + // rely on the URL of the download, because of possible collision between HEAD + // and GET requests. + std::map<const net::URLFetcher*, std::unique_ptr<Download>> downloads_; DISALLOW_COPY_AND_ASSIGN(PaymentManifestDownloader); };
diff --git a/components/payments/content/payment_manifest_downloader_unittest.cc b/components/payments/content/payment_manifest_downloader_unittest.cc index bc7d26b..a1266601 100644 --- a/components/payments/content/payment_manifest_downloader_unittest.cc +++ b/components/payments/content/payment_manifest_downloader_unittest.cc
@@ -15,22 +15,21 @@ namespace payments { namespace { -class PaymentMethodManifestDownloaderTest - : public testing::Test, - public PaymentManifestDownloader::Delegate { +class PaymentMethodManifestDownloaderTest : public testing::Test { public: PaymentMethodManifestDownloaderTest() : context_(new net::TestURLRequestContextGetter( base::ThreadTaskRunnerHandle::Get())), - downloader_(context_, GURL("https://bobpay.com"), this) { - downloader_.DownloadPaymentMethodManifest(); + downloader_(context_) { + downloader_.DownloadPaymentMethodManifest( + GURL("https://bobpay.com"), + base::BindOnce(&PaymentMethodManifestDownloaderTest::OnManifestDownload, + base::Unretained(this))); } ~PaymentMethodManifestDownloaderTest() override {} - // PaymentManifestDownloader::Delegate - MOCK_METHOD1(OnManifestDownloadSuccess, void(const std::string& content)); - MOCK_METHOD0(OnManifestDownloadFailure, void()); + MOCK_METHOD1(OnManifestDownload, void(const std::string& content)); net::TestURLFetcher* fetcher() { return factory_.GetFetcherByID(0); } @@ -46,7 +45,7 @@ TEST_F(PaymentMethodManifestDownloaderTest, HttpHeadResponse404IsFailure) { fetcher()->set_response_code(404); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -54,7 +53,7 @@ TEST_F(PaymentMethodManifestDownloaderTest, NoHttpHeadersIsFailure) { fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -65,7 +64,7 @@ fetcher()->set_response_headers(headers); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -77,7 +76,7 @@ fetcher()->set_response_headers(headers); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -89,7 +88,7 @@ fetcher()->set_response_headers(headers); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -101,7 +100,7 @@ fetcher()->set_response_headers(headers); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -114,7 +113,7 @@ fetcher()->set_response_headers(headers); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -128,7 +127,7 @@ fetcher()->delegate()->OnURLFetchComplete(fetcher()); fetcher()->set_response_code(404); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -142,7 +141,7 @@ fetcher()->delegate()->OnURLFetchComplete(fetcher()); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -157,7 +156,24 @@ fetcher()->SetResponseString("manifest content"); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadSuccess("manifest content")); + EXPECT_CALL(*this, OnManifestDownload("manifest content")); + + fetcher()->delegate()->OnURLFetchComplete(fetcher()); +} + +TEST_F(PaymentMethodManifestDownloaderTest, HeaderResponseCode204IsSuccess) { + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders(std::string())); + headers->AddHeader("Link: <manifest.json>; rel=payment-method-manifest"); + fetcher()->set_response_headers(headers); + // HTTP code 204 means "no content", which is not a problem for an HTTP HEAD + // request. + fetcher()->set_response_code(204); + fetcher()->delegate()->OnURLFetchComplete(fetcher()); + fetcher()->SetResponseString("manifest content"); + fetcher()->set_response_code(200); + + EXPECT_CALL(*this, OnManifestDownload("manifest content")); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -197,27 +213,26 @@ fetcher()->set_response_headers(headers); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } -class WebAppManifestDownloaderTest - : public testing::Test, - public PaymentManifestDownloader::Delegate { +class WebAppManifestDownloaderTest : public testing::Test { public: WebAppManifestDownloaderTest() : context_(new net::TestURLRequestContextGetter( base::ThreadTaskRunnerHandle::Get())), - downloader_(context_, GURL("https://bobpay.com"), this) { - downloader_.DownloadWebAppManifest(); + downloader_(context_) { + downloader_.DownloadWebAppManifest( + GURL("https://bobpay.com"), + base::BindOnce(&WebAppManifestDownloaderTest::OnManifestDownload, + base::Unretained(this))); } ~WebAppManifestDownloaderTest() override {} - // PaymentManifestDownloader::Delegate - MOCK_METHOD1(OnManifestDownloadSuccess, void(const std::string& content)); - MOCK_METHOD0(OnManifestDownloadFailure, void()); + MOCK_METHOD1(OnManifestDownload, void(const std::string& content)); net::TestURLFetcher* fetcher() { return factory_.GetFetcherByID(0); } @@ -233,7 +248,7 @@ TEST_F(WebAppManifestDownloaderTest, HttpGetResponse404IsFailure) { fetcher()->set_response_code(404); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -241,7 +256,7 @@ TEST_F(WebAppManifestDownloaderTest, EmptyHttpGetResponseIsFailure) { fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadFailure()); + EXPECT_CALL(*this, OnManifestDownload(std::string())); fetcher()->delegate()->OnURLFetchComplete(fetcher()); } @@ -250,7 +265,7 @@ fetcher()->SetResponseString("manifest content"); fetcher()->set_response_code(200); - EXPECT_CALL(*this, OnManifestDownloadSuccess("manifest content")); + EXPECT_CALL(*this, OnManifestDownload("manifest content")); fetcher()->delegate()->OnURLFetchComplete(fetcher()); }
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc index fce3e29..bc6a5a9 100644 --- a/components/payments/content/payment_request_spec.cc +++ b/components/payments/content/payment_request_spec.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_method_data.h" #include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" @@ -57,6 +58,68 @@ return autofill::CreditCard::CARD_TYPE_UNKNOWN; } +PaymentMethodData CreatePaymentMethodData( + const mojom::PaymentMethodDataPtr& method_data_entry) { + PaymentMethodData method_data; + method_data.supported_methods = method_data_entry->supported_methods; + + // Transfer the supported basic card networks (visa, amex) and types + // (credit, debit). + for (const mojom::BasicCardNetwork& network : + method_data_entry->supported_networks) { + method_data.supported_networks.push_back(GetBasicCardNetworkName(network)); + } + for (const mojom::BasicCardType& type : method_data_entry->supported_types) { + autofill::CreditCard::CardType card_type = GetBasicCardType(type); + method_data.supported_types.insert(card_type); + } + return method_data; +} + +// Validates the |method_data| and fills |supported_card_networks_|, +// |supported_card_networks_set_| and |basic_card_specified_networks_|. +void PopulateValidatedMethodData( + const std::vector<PaymentMethodData>& method_data_vector, + std::vector<std::string>* supported_card_networks, + std::set<std::string>* basic_card_specified_networks, + std::set<std::string>* supported_card_networks_set, + std::set<autofill::CreditCard::CardType>* supported_card_types_set, + std::map<std::string, std::set<std::string>>* stringified_method_data) { + data_util::ParseBasicCardSupportedNetworks(method_data_vector, + supported_card_networks, + basic_card_specified_networks); + supported_card_networks_set->insert(supported_card_networks->begin(), + supported_card_networks->end()); + + data_util::ParseSupportedCardTypes(method_data_vector, + supported_card_types_set); +} + +void PopulateValidatedMethodData( + const std::vector<mojom::PaymentMethodDataPtr>& method_data_mojom, + std::vector<std::string>* supported_card_networks, + std::set<std::string>* basic_card_specified_networks, + std::set<std::string>* supported_card_networks_set, + std::set<autofill::CreditCard::CardType>* supported_card_types_set, + std::map<std::string, std::set<std::string>>* stringified_method_data) { + std::vector<PaymentMethodData> method_data_vector; + method_data_vector.reserve(method_data_mojom.size()); + for (const mojom::PaymentMethodDataPtr& method_data_entry : + method_data_mojom) { + for (const std::string& method : method_data_entry->supported_methods) { + (*stringified_method_data)[method].insert( + method_data_entry->stringified_data); + } + + method_data_vector.push_back(CreatePaymentMethodData(method_data_entry)); + } + + PopulateValidatedMethodData( + method_data_vector, supported_card_networks, + basic_card_specified_networks, supported_card_networks_set, + supported_card_types_set, stringified_method_data); +} + } // namespace const char kBasicCardMethodName[] = "basic-card"; @@ -74,7 +137,10 @@ if (observer) AddObserver(observer); UpdateSelectedShippingOption(/*after_update=*/false); - PopulateValidatedMethodData(method_data); + PopulateValidatedMethodData( + method_data, &supported_card_networks_, &basic_card_specified_networks_, + &supported_card_networks_set_, &supported_card_types_set_, + &stringified_method_data_); } PaymentRequestSpec::~PaymentRequestSpec() {} @@ -161,44 +227,60 @@ }); } -void PaymentRequestSpec::PopulateValidatedMethodData( - const std::vector<mojom::PaymentMethodDataPtr>& method_data_mojom) { - std::vector<PaymentMethodData> method_data_vector; - method_data_vector.reserve(method_data_mojom.size()); - for (const mojom::PaymentMethodDataPtr& method_data_entry : - method_data_mojom) { - for (const std::string& method : method_data_entry->supported_methods) { - stringified_method_data_[method].insert( - method_data_entry->stringified_data); - } +const mojom::PaymentItemPtr& PaymentRequestSpec::GetTotal( + PaymentInstrument* selected_instrument) const { + const mojom::PaymentDetailsModifierPtr* modifier = + GetApplicableModifier(selected_instrument); + return modifier ? (*modifier)->total : details().total; +} - PaymentMethodData method_data; - method_data.supported_methods = method_data_entry->supported_methods; - - // Transfer the supported basic card networks (visa, amex) and types - // (credit, debit). - for (const mojom::BasicCardNetwork& network : - method_data_entry->supported_networks) { - method_data.supported_networks.push_back( - GetBasicCardNetworkName(network)); - } - for (const mojom::BasicCardType& type : - method_data_entry->supported_types) { - autofill::CreditCard::CardType card_type = GetBasicCardType(type); - method_data.supported_types.insert(card_type); - } - - method_data_vector.push_back(std::move(method_data)); +std::vector<const mojom::PaymentItemPtr*> PaymentRequestSpec::GetDisplayItems( + PaymentInstrument* selected_instrument) const { + std::vector<const mojom::PaymentItemPtr*> display_items; + const mojom::PaymentDetailsModifierPtr* modifier = + GetApplicableModifier(selected_instrument); + for (const auto& item : details().display_items) { + display_items.push_back(&item); } - data_util::ParseBasicCardSupportedNetworks(method_data_vector, - &supported_card_networks_, - &basic_card_specified_networks_); - supported_card_networks_set_.insert(supported_card_networks_.begin(), - supported_card_networks_.end()); + if (modifier) { + for (const auto& additional_item : (*modifier)->additional_display_items) { + display_items.push_back(&additional_item); + } + } + return display_items; +} - data_util::ParseSupportedCardTypes(method_data_vector, - &supported_card_types_set_); +const std::vector<mojom::PaymentShippingOptionPtr>& +PaymentRequestSpec::GetShippingOptions() const { + return details().shipping_options; +} + +const mojom::PaymentDetailsModifierPtr* +PaymentRequestSpec::GetApplicableModifier( + PaymentInstrument* selected_instrument) const { + if (!selected_instrument) + return nullptr; + + for (const auto& modifier : details().modifiers) { + std::vector<std::string> supported_networks; + std::set<autofill::CreditCard::CardType> supported_types; + // The following 3 are unused but required by PopulateValidatedMethodData. + std::set<std::string> basic_card_specified_networks; + std::set<std::string> supported_card_networks_set; + std::map<std::string, std::set<std::string>> stringified_method_data; + PopulateValidatedMethodData( + {CreatePaymentMethodData(modifier->method_data)}, &supported_networks, + &basic_card_specified_networks, &supported_card_networks_set, + &supported_types, &stringified_method_data); + + if (selected_instrument->IsValidForModifier( + modifier->method_data->supported_methods, supported_types, + supported_networks)) { + return &modifier; + } + } + return nullptr; } void PaymentRequestSpec::UpdateSelectedShippingOption(bool after_update) {
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h index 9170efaf..9930459 100644 --- a/components/payments/content/payment_request_spec.h +++ b/components/payments/content/payment_request_spec.h
@@ -20,6 +20,8 @@ namespace payments { +class PaymentInstrument; + // Identifier for the basic card payment method in the PaymentMethodData. extern const char kBasicCardMethodName[]; @@ -112,19 +114,30 @@ return selected_shipping_option_error_; } - const mojom::PaymentDetails& details() const { return *details_.get(); } - void StartWaitingForUpdateWith(UpdateReason reason); - bool IsMixedCurrency() const; UpdateReason current_update_reason() const { return current_update_reason_; } + // Returns the total object of this payment request, taking into account the + // applicable modifier for |selected_instrument| if any. + const mojom::PaymentItemPtr& GetTotal( + PaymentInstrument* selected_instrument) const; + // Returns the display items for this payment request, taking into account the + // applicable modifier for |selected_instrument| if any. + std::vector<const mojom::PaymentItemPtr*> GetDisplayItems( + PaymentInstrument* selected_instrument) const; + + const std::vector<mojom::PaymentShippingOptionPtr>& GetShippingOptions() + const; + private: - // Validates the |method_data| and fills |supported_card_networks_|, - // |supported_card_networks_set_| and |basic_card_specified_networks_|. - void PopulateValidatedMethodData( - const std::vector<mojom::PaymentMethodDataPtr>& method_data); + // Returns the first applicable modifier in the Payment Request for the + // |selected_instrument|. + const mojom::PaymentDetailsModifierPtr* GetApplicableModifier( + PaymentInstrument* selected_instrument) const; + + const mojom::PaymentDetails& details() const { return *details_.get(); } // Updates the |selected_shipping_option| based on the data passed to this // payment request by the website. This will set selected_shipping_option_ to
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc index 1fefb16..f62ed9b 100644 --- a/components/payments/content/payment_request_state.cc +++ b/components/payments/content/payment_request_state.cc
@@ -298,6 +298,9 @@ journey_logger_->SetNumberOfSuggestionsShown( JourneyLogger::Section::SECTION_CREDIT_CARDS, available_instruments().size()); + + if (!available_instruments().empty()) + journey_logger_->SetUserHadInitialFormOfPayment(); } void PaymentRequestState::SetDefaultProfileSelections() {
diff --git a/components/payments/core/autofill_payment_instrument.cc b/components/payments/core/autofill_payment_instrument.cc index c18e195..2b096c3 100644 --- a/components/payments/core/autofill_payment_instrument.cc +++ b/components/payments/core/autofill_payment_instrument.cc
@@ -4,6 +4,7 @@ #include "components/payments/core/autofill_payment_instrument.h" +#include <algorithm> #include <memory> #include "base/json/json_writer.h" @@ -122,6 +123,44 @@ autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL), app_locale_); } +bool AutofillPaymentInstrument::IsValidForModifier( + const std::vector<std::string>& method, + const std::set<autofill::CreditCard::CardType>& supported_types, + const std::vector<std::string>& supported_networks) const { + // This instrument only matches basic-card. + if (std::find(method.begin(), method.end(), "basic-card") == method.end()) + return false; + + // If supported_types is not specified and this instrument matches the method, + // the modifier is applicable. If supported_types is populated, it must + // contain this card's type to be applicable. The same is true for + // supported_networks. + bool is_supported_type = + supported_types.empty() || + std::find(supported_types.begin(), supported_types.end(), + credit_card_.card_type()) != supported_types.end(); + + // supported_types may contain CARD_TYPE_UNKNOWN because of the parsing + // function but the modifiers shouldn't be applied since the website can't be + // sure that the instrument is an applicable card. + if (is_supported_type && + credit_card_.card_type() == + autofill::CreditCard::CardType::CARD_TYPE_UNKNOWN) + return false; + + bool is_supported_network = supported_networks.empty(); + if (!is_supported_network) { + std::string basic_card_network = + autofill::data_util::GetPaymentRequestData(credit_card_.network()) + .basic_card_issuer_network; + is_supported_network = + std::find(supported_networks.begin(), supported_networks.end(), + basic_card_network) != supported_networks.end(); + } + + return is_supported_type && is_supported_network; +} + void AutofillPaymentInstrument::OnFullCardRequestSucceeded( const autofill::CreditCard& card, const base::string16& cvc) {
diff --git a/components/payments/core/autofill_payment_instrument.h b/components/payments/core/autofill_payment_instrument.h index c3b2944b..7ec5071 100644 --- a/components/payments/core/autofill_payment_instrument.h +++ b/components/payments/core/autofill_payment_instrument.h
@@ -48,6 +48,10 @@ void RecordUse() override; base::string16 GetLabel() const override; base::string16 GetSublabel() const override; + bool IsValidForModifier( + const std::vector<std::string>& method, + const std::set<autofill::CreditCard::CardType>& supported_types, + const std::vector<std::string>& supported_networks) const override; // autofill::payments::FullCardRequest::ResultDelegate: void OnFullCardRequestSucceeded(const autofill::CreditCard& card,
diff --git a/components/payments/core/journey_logger.cc b/components/payments/core/journey_logger.cc index ccf337b3..ae2d4b6 100644 --- a/components/payments/core/journey_logger.cc +++ b/components/payments/core/journey_logger.cc
@@ -106,6 +106,29 @@ was_show_called_ = true; } +void JourneyLogger::SetEventOccurred(Event event) { + events_ |= event; +} + +void JourneyLogger::SetSelectedPaymentMethod( + SelectedPaymentMethod payment_method) { + payment_method_ = payment_method; +} + +void JourneyLogger::SetRequestedInformation(bool requested_shipping, + bool requested_email, + bool requested_phone, + bool requested_name) { + // This method should only be called once per Payment Request. + DCHECK(requested_information_ == REQUESTED_INFORMATION_MAX); + + requested_information_ = + (requested_shipping ? REQUESTED_INFORMATION_SHIPPING : 0) | + (requested_email ? REQUESTED_INFORMATION_EMAIL : 0) | + (requested_phone ? REQUESTED_INFORMATION_PHONE : 0) | + (requested_name ? REQUESTED_INFORMATION_NAME : 0); +} + void JourneyLogger::SetCompleted() { UMA_HISTOGRAM_BOOLEAN("PaymentRequest.CheckoutFunnel.Completed", true); @@ -135,27 +158,8 @@ UMA_HISTOGRAM_BOOLEAN("PaymentRequest.CheckoutFunnel.Initiated", true); } -void JourneyLogger::SetEventOccurred(Event event) { - events_ |= event; -} - -void JourneyLogger::SetSelectedPaymentMethod( - SelectedPaymentMethod payment_method) { - payment_method_ = payment_method; -} - -void JourneyLogger::SetRequestedInformation(bool requested_shipping, - bool requested_email, - bool requested_phone, - bool requested_name) { - // This method should only be called once per Payment Request. - DCHECK(requested_information_ == REQUESTED_INFORMATION_MAX); - - requested_information_ = - (requested_shipping ? REQUESTED_INFORMATION_SHIPPING : 0) | - (requested_email ? REQUESTED_INFORMATION_EMAIL : 0) | - (requested_phone ? REQUESTED_INFORMATION_PHONE : 0) | - (requested_name ? REQUESTED_INFORMATION_NAME : 0); +void JourneyLogger::SetUserHadInitialFormOfPayment() { + user_had_initial_form_of_payment_ = true; } void JourneyLogger::RecordJourneyStatsHistograms( @@ -249,6 +253,20 @@ "EffectOnCompletion", completion_status, COMPLETION_STATUS_MAX); } + + // Recond the metric about completion status based on whether the user + // initally had a form of payment on file. + if (user_had_initial_form_of_payment_) { + base::UmaHistogramEnumeration( + "PaymentRequest.UserHadInitialFormOfPayment." + "EffectOnCompletion", + completion_status, COMPLETION_STATUS_MAX); + } else { + base::UmaHistogramEnumeration( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment." + "EffectOnCompletion", + completion_status, COMPLETION_STATUS_MAX); + } } void JourneyLogger::RecordCanMakePaymentStats(
diff --git a/components/payments/core/journey_logger.h b/components/payments/core/journey_logger.h index 4fba129..143903fa 100644 --- a/components/payments/core/journey_logger.h +++ b/components/payments/core/journey_logger.h
@@ -186,6 +186,10 @@ // reason. void SetNotShown(NotShownReason reason); + // Records the fact that the user had a Payment Method on file at the start of + // the Payment Request. + void SetUserHadInitialFormOfPayment(); + private: static const int NUMBER_OF_SECTIONS = 3; @@ -254,6 +258,7 @@ bool was_can_make_payments_used_ = false; bool could_make_payment_ = false; bool was_show_called_ = false; + bool user_had_initial_form_of_payment_ = false; bool is_incognito_; // Accumulates the many events that have happened during the Payment Request.
diff --git a/components/payments/core/journey_logger_unittest.cc b/components/payments/core/journey_logger_unittest.cc index 2fd288e..394960f 100644 --- a/components/payments/core/journey_logger_unittest.cc +++ b/components/payments/core/journey_logger_unittest.cc
@@ -693,6 +693,85 @@ testing::ContainerEq(base::HistogramTester::CountsMap())); } +// Tests that the UserHadInitialFormOfPayment metric is correctly logged. +TEST(JourneyLoggerTest, + RecordJourneyStatsHistograms_UserHadInitialFormOfPayment) { + base::HistogramTester histogram_tester; + JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), + /*ukm_recorder=*/nullptr); + + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + + // Simulate that the user had an inital form of payment. + logger.SetUserHadInitialFormOfPayment(); + + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + + // Simulate that the the checkout is aborted. + logger.SetAborted(JourneyLogger::ABORT_REASON_OTHER); + + histogram_tester.ExpectBucketCount( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", + JourneyLogger::COMPLETION_STATUS_OTHER_ABORTED, 1); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + 0); +} + +// Tests that the UserDidNotHaveInitialFormOfPayment metric is correctly logged. +TEST(JourneyLoggerTest, + RecordJourneyStatsHistograms_UserDidNotHaveInitialFormOfPayment) { + base::HistogramTester histogram_tester; + JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), + /*ukm_recorder=*/nullptr); + + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + + // Simulate that the the checkout is aborted. + logger.SetAborted(JourneyLogger::ABORT_REASON_OTHER); + + histogram_tester.ExpectBucketCount( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + JourneyLogger::COMPLETION_STATUS_OTHER_ABORTED, 1); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", 0); +} + +// Tests that the InitialFormOfPayment metrics are only logged if the Payment +// Request is shown. +TEST(JourneyLoggerTest, + RecordJourneyStatsHistograms_InitialFormOfPayment_NotShown) { + base::HistogramTester histogram_tester; + JourneyLogger logger_with_fop(/*is_incognito=*/false, /*url=*/GURL(""), + /*ukm_recorder=*/nullptr); + JourneyLogger logger_without_fop(/*is_incognito=*/false, /*url=*/GURL(""), + /*ukm_recorder=*/nullptr); + + // Set that the user had an initial form of payment. + logger_with_fop.SetUserHadInitialFormOfPayment(); + + // Simulate that the the checkouts are aborted. + logger_with_fop.SetAborted(JourneyLogger::ABORT_REASON_OTHER); + logger_without_fop.SetAborted(JourneyLogger::ABORT_REASON_ABORTED_BY_USER); + + // There should be no logs for the two metrics. + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion", + 0); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion", 0); +} + // Tests that the metrics are logged correctly for two simultaneous Payment // Requests. TEST(JourneyLoggerTest, RecordJourneyStatsHistograms_TwoPaymentRequests) {
diff --git a/components/payments/core/payment_instrument.h b/components/payments/core/payment_instrument.h index f189c02..ecdc99e 100644 --- a/components/payments/core/payment_instrument.h +++ b/components/payments/core/payment_instrument.h
@@ -7,9 +7,11 @@ #include <set> #include <string> +#include <vector> #include "base/macros.h" #include "base/strings/string16.h" +#include "components/autofill/core/browser/credit_card.h" namespace payments { @@ -55,6 +57,13 @@ virtual base::string16 GetLabel() const = 0; virtual base::string16 GetSublabel() const = 0; + // Returns true if this payment instrument can be used to fulfill a request + // specifying |method| as a supported method of payment, false otherwise. + virtual bool IsValidForModifier( + const std::vector<std::string>& method, + const std::set<autofill::CreditCard::CardType>& supported_types, + const std::vector<std::string>& supported_networks) const = 0; + const std::string& method_name() const { return method_name_; } int icon_resource_id() const { return icon_resource_id_; } Type type() { return type_; }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 03305bf..99f9c91f 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -5394,7 +5394,7 @@ 'id': 127, 'caption': '''Enable metrics reporting''', 'tags': ['admin-sharing'], - 'desc': '''Controls whether usage metrics are reported back to Google. If set to true, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will report usage metrics. If not configured or set to false, metrics reporting will be disabled.''', + 'desc': '''Controls whether usage metrics and diagnostic data, including crash reports, are reported back to Google. If set to true, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will report usage metrics and diagnostic data. If not configured or set to false, metrics and diagnostic data reporting will be disabled.''', 'arc_support': 'This policy also controls Android usage and diagnostic data collection.', }, {
diff --git a/components/safe_browsing/csd.proto b/components/safe_browsing/csd.proto index e33f34c7..b561039 100644 --- a/components/safe_browsing/csd.proto +++ b/components/safe_browsing/csd.proto
@@ -483,7 +483,8 @@ // Fields 19-21 are reserved for server-side use and are never sent by the // client. - // A binary contained in an archive (e.g., a .zip archive). + // A binary or archive contained in an archive (e.g., a .exe in a .zip + // archive, or a .zip inside a .zip). message ArchivedBinary { optional string file_basename = 1; optional DownloadType download_type = 2;
diff --git a/components/search_provider_logos/logo_cache.cc b/components/search_provider_logos/logo_cache.cc index 70fbe7b..3c4b272 100644 --- a/components/search_provider_logos/logo_cache.cc +++ b/components/search_provider_logos/logo_cache.cc
@@ -57,16 +57,16 @@ : cache_directory_(cache_directory), metadata_is_valid_(false) { // The LogoCache can be constructed on any thread, as long as it's used - // on a single thread after construction. - thread_checker_.DetachFromThread(); + // on a single sequence after construction. + DETACH_FROM_SEQUENCE(sequence_checker_); } LogoCache::~LogoCache() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } void LogoCache::UpdateCachedLogoMetadata(const LogoMetadata& metadata) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(metadata_); DCHECK_EQ(metadata_->fingerprint, metadata.fingerprint); @@ -75,24 +75,24 @@ } const LogoMetadata* LogoCache::GetCachedLogoMetadata() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ReadMetadataIfNeeded(); return metadata_.get(); } void LogoCache::SetCachedLogo(const EncodedLogo* logo) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::unique_ptr<LogoMetadata> metadata; if (logo) { - metadata.reset(new LogoMetadata(logo->metadata)); + metadata = base::MakeUnique<LogoMetadata>(logo->metadata); logo_num_bytes_ = static_cast<int>(logo->encoded_image->size()); } UpdateMetadata(std::move(metadata)); - WriteLogo(logo ? logo->encoded_image : NULL); + WriteLogo(logo ? logo->encoded_image : nullptr); } std::unique_ptr<EncodedLogo> LogoCache::GetCachedLogo() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ReadMetadataIfNeeded(); if (!metadata_)
diff --git a/components/search_provider_logos/logo_cache.h b/components/search_provider_logos/logo_cache.h index e4a19af..da421c4 100644 --- a/components/search_provider_logos/logo_cache.h +++ b/components/search_provider_logos/logo_cache.h
@@ -43,14 +43,14 @@ // Updates the metadata for the cached logo. virtual void UpdateCachedLogoMetadata(const LogoMetadata& metadata); - // Returns metadata for the cached logo, or NULL if logo is cached. + // Returns metadata for the cached logo, or null if logo is cached. virtual const LogoMetadata* GetCachedLogoMetadata(); - // Sets the cached logo and metadata. |logo| may be NULL, in which case the + // Sets the cached logo and metadata. |logo| may be null, in which case the // cached logo and metadata will be cleared. virtual void SetCachedLogo(const EncodedLogo* logo); - // Returns the cached logo, or NULL if no logo is cached or the cached logo is + // Returns the cached logo, or null if no logo is cached or the cached logo is // corrupt. virtual std::unique_ptr<EncodedLogo> GetCachedLogo(); @@ -62,7 +62,7 @@ FRIEND_TEST_ALL_PREFIXES(LogoCacheTest, RetrieveCorruptMetadata); FRIEND_TEST_ALL_PREFIXES(LogoCacheTest, RetrieveCorruptLogo); - // Converts string |str| to a LogoMetadata object and returns it. Returns NULL + // Converts string |str| to a LogoMetadata object and returns it. Returns null // if |str| cannot be converted. static std::unique_ptr<LogoMetadata> LogoMetadataFromString( const std::string& str, @@ -84,7 +84,7 @@ // If the cached logo's metadata isn't available in memory (i.e. // |metadata_is_valid_| is false), reads it from disk and stores it in - // |metadata_|. If no logo is cached, |metadata_| will be updated to NULL. + // |metadata_|. If no logo is cached, |metadata_| will be updated to null. void ReadMetadataIfNeeded(); // Writes the metadata for the cached logo to disk. @@ -104,9 +104,9 @@ // The directory in which the cached logo and metadata will be saved. base::FilePath cache_directory_; - // The metadata describing the cached logo, or NULL if no logo is cached. This + // The metadata describing the cached logo, or null if no logo is cached. This // value is meaningful iff |metadata_is_valid_| is true; otherwise, the - // metadata must be read from file and |metadata_| will be NULL. + // metadata must be read from file and |metadata_| will be null. // Note: Once read from file, metadata will be stored in memory indefinitely. std::unique_ptr<LogoMetadata> metadata_; bool metadata_is_valid_; @@ -116,8 +116,8 @@ // is complete and corresponds to the current metadata file. int logo_num_bytes_; - // Ensure LogoCache is only used on a single thread. - base::ThreadChecker thread_checker_; + // Ensure LogoCache is only used sequentially. + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(LogoCache); };
diff --git a/components/search_provider_logos/logo_cache_unittest.cc b/components/search_provider_logos/logo_cache_unittest.cc index 0de7e38..2e0ca57 100644 --- a/components/search_provider_logos/logo_cache_unittest.cc +++ b/components/search_provider_logos/logo_cache_unittest.cc
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" @@ -55,17 +56,17 @@ return encoded_image_str; } -EncodedLogo GetExampleLogo() { - EncodedLogo logo; - logo.encoded_image = CreateExampleImage(837); - logo.metadata = GetExampleMetadata(); +std::unique_ptr<EncodedLogo> GetExampleLogo() { + auto logo = base::MakeUnique<EncodedLogo>(); + logo->encoded_image = CreateExampleImage(837); + logo->metadata = GetExampleMetadata(); return logo; } -EncodedLogo GetExampleLogo2() { - EncodedLogo logo; - logo.encoded_image = CreateExampleImage(345); - logo.metadata = GetExampleMetadata2(); +std::unique_ptr<EncodedLogo> GetExampleLogo2() { + auto logo = base::MakeUnique<EncodedLogo>(); + logo->encoded_image = CreateExampleImage(345); + logo->metadata = GetExampleMetadata2(); return logo; } @@ -106,27 +107,27 @@ } void InitCache() { - cache_.reset(new LogoCache( - cache_parent_dir_.GetPath().Append(FILE_PATH_LITERAL("cache")))); + cache_ = base::MakeUnique<LogoCache>( + cache_parent_dir_.GetPath().Append(FILE_PATH_LITERAL("cache"))); } void ExpectMetadata(const LogoMetadata* expected_metadata) { const LogoMetadata* retrieved_metadata = cache_->GetCachedLogoMetadata(); if (expected_metadata) { - ASSERT_TRUE(retrieved_metadata != NULL); + ASSERT_TRUE(retrieved_metadata); ExpectMetadataEqual(*expected_metadata, *retrieved_metadata); } else { - ASSERT_TRUE(retrieved_metadata == NULL); + ASSERT_FALSE(retrieved_metadata); } } void ExpectLogo(const EncodedLogo* expected_logo) { std::unique_ptr<EncodedLogo> retrieved_logo(cache_->GetCachedLogo()); if (expected_logo) { - ASSERT_TRUE(retrieved_logo.get() != NULL); + ASSERT_TRUE(retrieved_logo.get()); ExpectLogosEqual(*expected_logo, *retrieved_logo); } else { - ASSERT_TRUE(retrieved_logo.get() == NULL); + ASSERT_FALSE(retrieved_logo.get()); } } @@ -157,7 +158,7 @@ int logo_num_bytes = 33; std::unique_ptr<LogoMetadata> metadata = LogoCache::LogoMetadataFromString("", &logo_num_bytes); - ASSERT_TRUE(metadata.get() == NULL); + ASSERT_FALSE(metadata); LogoMetadata example_metadata = GetExampleMetadata2(); std::string corrupt_str; @@ -165,17 +166,17 @@ example_metadata, logo_num_bytes, &corrupt_str); corrupt_str.append("@"); metadata = LogoCache::LogoMetadataFromString(corrupt_str, &logo_num_bytes); - ASSERT_TRUE(metadata.get() == NULL); + ASSERT_FALSE(metadata); } TEST_F(LogoCacheTest, StoreAndRetrieveMetadata) { // Expect no metadata at first. - ExpectMetadata(NULL); + ExpectMetadata(nullptr); // Set initial metadata. - EncodedLogo logo = GetExampleLogo(); - LogoMetadata& metadata = logo.metadata; - cache_->SetCachedLogo(&logo); + std::unique_ptr<EncodedLogo> logo = GetExampleLogo(); + LogoMetadata& metadata = logo->metadata; + cache_->SetCachedLogo(logo.get()); ExpectMetadata(&metadata); // Update metadata. @@ -194,42 +195,42 @@ TEST_F(LogoCacheTest, StoreAndRetrieveLogo) { // Expect no metadata at first. - ExpectLogo(NULL); + ExpectLogo(nullptr); // Set initial logo. - EncodedLogo logo = GetExampleLogo(); - cache_->SetCachedLogo(&logo); - ExpectLogo(&logo); + std::unique_ptr<EncodedLogo> logo = GetExampleLogo(); + cache_->SetCachedLogo(logo.get()); + ExpectLogo(logo.get()); - // Update logo to NULL. - cache_->SetCachedLogo(NULL); - ExpectLogo(NULL); + // Update logo to null. + cache_->SetCachedLogo(nullptr); + ExpectLogo(nullptr); // Read logo back from disk. SimulateRestart(); - ExpectLogo(NULL); + ExpectLogo(nullptr); // Update logo. logo = GetExampleLogo2(); - cache_->SetCachedLogo(&logo); - ExpectLogo(&logo); + cache_->SetCachedLogo(logo.get()); + ExpectLogo(logo.get()); // Read logo back from disk. SimulateRestart(); - ExpectLogo(&logo); + ExpectLogo(logo.get()); } TEST_F(LogoCacheTest, RetrieveCorruptMetadata) { // Set initial logo. - EncodedLogo logo = GetExampleLogo2(); - cache_->SetCachedLogo(&logo); - ExpectLogo(&logo); + std::unique_ptr<EncodedLogo> logo = GetExampleLogo2(); + cache_->SetCachedLogo(logo.get()); + ExpectLogo(logo.get()); - // Corrupt metadata and expect NULL for both logo and metadata. + // Corrupt metadata and expect null for both logo and metadata. SimulateRestart(); ShortenFile(cache_->GetMetadataPath()); - ExpectMetadata(NULL); - ExpectLogo(NULL); + ExpectMetadata(nullptr); + ExpectLogo(nullptr); // Ensure corrupt cache files are deleted. EXPECT_FALSE(base::PathExists(cache_->GetMetadataPath())); @@ -238,16 +239,17 @@ TEST_F(LogoCacheTest, RetrieveCorruptLogo) { // Set initial logo. - EncodedLogo logo = GetExampleLogo(); - cache_->SetCachedLogo(&logo); - ExpectLogo(&logo); + std::unique_ptr<EncodedLogo> logo = GetExampleLogo(); + cache_->SetCachedLogo(logo.get()); + ExpectLogo(logo.get()); - // Corrupt logo and expect NULL. + // Corrupt logo and expect nullptr. SimulateRestart(); ShortenFile(cache_->GetLogoPath()); - ExpectLogo(NULL); - // Once the logo is noticed to be NULL, the metadata should also be cleared. - ExpectMetadata(NULL); + ExpectLogo(nullptr); + + // Once the logo is noticed to be null, the metadata should also be cleared. + ExpectMetadata(nullptr); // Ensure corrupt cache files are deleted. EXPECT_FALSE(base::PathExists(cache_->GetMetadataPath()));
diff --git a/components/search_provider_logos/logo_tracker.cc b/components/search_provider_logos/logo_tracker.cc index d4d0bcf..021e52e 100644 --- a/components/search_provider_logos/logo_tracker.cc +++ b/components/search_provider_logos/logo_tracker.cc
@@ -7,10 +7,12 @@ #include <algorithm> #include <utility> +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_clock.h" #include "components/data_use_measurement/core/data_use_user_data.h" @@ -62,33 +64,26 @@ return logo_cache->GetCachedLogo(); } -void DeleteLogoCacheOnFileThread(LogoCache* logo_cache) { - delete logo_cache; -} - } // namespace LogoTracker::LogoTracker( base::FilePath cached_logo_directory, - scoped_refptr<base::SequencedTaskRunner> file_task_runner, - scoped_refptr<base::TaskRunner> background_task_runner, scoped_refptr<net::URLRequestContextGetter> request_context_getter, std::unique_ptr<LogoDelegate> delegate) : is_idle_(true), is_cached_logo_valid_(false), logo_delegate_(std::move(delegate)), - logo_cache_(new LogoCache(cached_logo_directory)), - clock_(new base::DefaultClock()), - file_task_runner_(file_task_runner), - background_task_runner_(background_task_runner), + cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), + logo_cache_(new LogoCache(cached_logo_directory), + base::OnTaskRunnerDeleter(cache_task_runner_)), + clock_(base::MakeUnique<base::DefaultClock>()), request_context_getter_(request_context_getter), weak_ptr_factory_(this) {} LogoTracker::~LogoTracker() { ReturnToIdle(kDownloadOutcomeNotTracked); - file_task_runner_->PostTask( - FROM_HERE, base::Bind(&DeleteLogoCacheOnFileThread, logo_cache_)); - logo_cache_ = NULL; } void LogoTracker::SetServerAPI( @@ -112,11 +107,9 @@ if (is_idle_) { is_idle_ = false; base::PostTaskAndReplyWithResult( - file_task_runner_.get(), - FROM_HERE, + cache_task_runner_.get(), FROM_HERE, base::Bind(&GetLogoFromCacheOnFileThread, - logo_cache_, - logo_url_, + base::Unretained(logo_cache_.get()), logo_url_, clock_->Now()), base::Bind(&LogoTracker::OnCachedLogoRead, weak_ptr_factory_.GetWeakPtr())); @@ -131,9 +124,9 @@ void LogoTracker::SetLogoCacheForTests(std::unique_ptr<LogoCache> cache) { DCHECK(cache); - file_task_runner_->PostTask( - FROM_HERE, base::Bind(&DeleteLogoCacheOnFileThread, logo_cache_)); - logo_cache_ = cache.release(); + // Call reset() and release() to keep the deleter of the |logo_cache_| member + // and run it on the old value. + logo_cache_.reset(cache.release()); } void LogoTracker::SetClockForTests(std::unique_ptr<base::Clock> clock) { @@ -191,18 +184,16 @@ } void LogoTracker::SetCachedLogo(std::unique_ptr<EncodedLogo> logo) { - file_task_runner_->PostTask( + cache_task_runner_->PostTask( FROM_HERE, - base::Bind(&LogoCache::SetCachedLogo, - base::Unretained(logo_cache_), + base::Bind(&LogoCache::SetCachedLogo, base::Unretained(logo_cache_.get()), base::Owned(logo.release()))); } void LogoTracker::SetCachedMetadata(const LogoMetadata& metadata) { - file_task_runner_->PostTask(FROM_HERE, - base::Bind(&LogoCache::UpdateCachedLogoMetadata, - base::Unretained(logo_cache_), - metadata)); + cache_task_runner_->PostTask( + FROM_HERE, base::Bind(&LogoCache::UpdateCachedLogoMetadata, + base::Unretained(logo_cache_.get()), metadata)); } void LogoTracker::FetchLogo() { @@ -362,8 +353,10 @@ bool from_http_cache = source->WasCached(); bool* parsing_failed = new bool(false); - base::PostTaskAndReplyWithResult( - background_task_runner_.get(), FROM_HERE, + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::Bind(parse_logo_response_func_, base::Passed(&response), response_time, parsing_failed), base::Bind(&LogoTracker::OnFreshLogoParsed,
diff --git a/components/search_provider_logos/logo_tracker.h b/components/search_provider_logos/logo_tracker.h index af8a10b..1362f75 100644 --- a/components/search_provider_logos/logo_tracker.h +++ b/components/search_provider_logos/logo_tracker.h
@@ -93,9 +93,6 @@ // |cached_logo_directory| is the directory in which the cached logo and its // metadata should be saved. // - // |file_task_runner| is the SequencedTaskRunner that should be used to run - // file system operations. - // // |background_task_runner| is the TaskRunner that should be used to for // CPU-intensive background operations. // @@ -103,8 +100,6 @@ // the logo. explicit LogoTracker( base::FilePath cached_logo_directory, - scoped_refptr<base::SequencedTaskRunner> file_task_runner, - scoped_refptr<base::TaskRunner> background_task_runner, scoped_refptr<net::URLRequestContextGetter> request_context_getter, std::unique_ptr<LogoDelegate> delegate); @@ -234,18 +229,16 @@ std::unique_ptr<LogoDelegate> logo_delegate_; - // The cache used to persist the logo on disk. Used only on the file thread. - LogoCache* logo_cache_; + // The SequencedTaskRunner on which the cache lives. + scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; + + // The cache used to persist the logo on disk. Used only on a background + // SequencedTaskRunner. + std::unique_ptr<LogoCache, base::OnTaskRunnerDeleter> logo_cache_; // Clock used to determine current time. Can be overridden in tests. std::unique_ptr<base::Clock> clock_; - // The SequencedTaskRunner on which file system operations will be run. - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - - // The TaskRunner on which the server's response will be parsed. - scoped_refptr<base::TaskRunner> background_task_runner_; - // The URLRequestContextGetter used for network requests. scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
diff --git a/components/search_provider_logos/logo_tracker_unittest.cc b/components/search_provider_logos/logo_tracker_unittest.cc index acd3c7b..346ee57 100644 --- a/components/search_provider_logos/logo_tracker_unittest.cc +++ b/components/search_provider_logos/logo_tracker_unittest.cc
@@ -21,6 +21,7 @@ #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" +#include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -188,7 +189,7 @@ Logo actual_logo; if (actual_encoded_logo) actual_logo = DecodeLogo(*actual_encoded_logo); - ExpectLogosEqual(expected_logo, actual_encoded_logo ? &actual_logo : NULL); + ExpectLogosEqual(expected_logo, actual_encoded_logo ? &actual_logo : nullptr); } ACTION_P(ExpectLogosEqualAction, expected_logo) { @@ -234,18 +235,18 @@ logo_->metadata = metadata; } - virtual const LogoMetadata* GetCachedLogoMetadataInternal() { + const LogoMetadata* GetCachedLogoMetadataInternal() { return metadata_.get(); } - virtual void SetCachedLogoInternal(const EncodedLogo* logo) { - logo_.reset(logo ? new EncodedLogo(*logo) : NULL); - metadata_.reset(logo ? new LogoMetadata(logo->metadata) : NULL); + void SetCachedLogoInternal(const EncodedLogo* logo) { + logo_ = logo ? base::MakeUnique<EncodedLogo>(*logo) : nullptr; + metadata_ = logo ? base::MakeUnique<LogoMetadata>(logo->metadata) : nullptr; } std::unique_ptr<EncodedLogo> GetCachedLogo() override { OnGetCachedLogo(); - return base::WrapUnique(logo_ ? new EncodedLogo(*logo_) : NULL); + return logo_ ? base::MakeUnique<EncodedLogo>(*logo_) : nullptr; } private: @@ -274,7 +275,7 @@ void ExpectFreshLogo(const Logo* expected_fresh_logo) { Mock::VerifyAndClearExpectations(this); EXPECT_CALL(*this, OnLogoAvailable(_, true)).Times(0); - EXPECT_CALL(*this, OnLogoAvailable(NULL, true)); + EXPECT_CALL(*this, OnLogoAvailable(nullptr, true)); EXPECT_CALL(*this, OnLogoAvailable(_, false)) .WillOnce(ExpectLogosEqualAction(expected_fresh_logo)); EXPECT_CALL(*this, OnObserverRemoved()).Times(1); @@ -314,32 +315,29 @@ class LogoTrackerTest : public ::testing::Test { protected: LogoTrackerTest() - : message_loop_(new base::MessageLoop()), - logo_url_("https://google.com/doodleoftheday?size=hp"), + : logo_url_("https://google.com/doodleoftheday?size=hp"), test_clock_(new base::SimpleTestClock()), logo_cache_(new NiceMock<MockLogoCache>()), - fake_url_fetcher_factory_(NULL) { + fake_url_fetcher_factory_(nullptr) { test_clock_->SetNow(base::Time::FromJsTime(INT64_C(1388686828000))); logo_tracker_ = - new LogoTracker(base::FilePath(), base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get(), - new net::TestURLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get()), - std::unique_ptr<LogoDelegate>(new TestLogoDelegate())); + base::MakeUnique<LogoTracker>(base::FilePath(), + new net::TestURLRequestContextGetter( + base::ThreadTaskRunnerHandle::Get()), + base::MakeUnique<TestLogoDelegate>()); logo_tracker_->SetServerAPI( logo_url_, base::Bind(&GoogleParseLogoResponse), base::Bind(&GoogleAppendQueryparamsToLogoURL, false)); - logo_tracker_->SetClockForTests(std::unique_ptr<base::Clock>(test_clock_)); - logo_tracker_->SetLogoCacheForTests( - std::unique_ptr<LogoCache>(logo_cache_)); + logo_tracker_->SetClockForTests(base::WrapUnique(test_clock_)); + logo_tracker_->SetLogoCacheForTests(base::WrapUnique(logo_cache_)); } - virtual void TearDown() { - // logo_tracker_ owns logo_cache_, which gets destructed on the file thread - // after logo_tracker_'s destruction. Ensure that logo_cache_ is actually - // destructed before the test ends to make gmock happy. - delete logo_tracker_; - base::RunLoop().RunUntilIdle(); + void TearDown() override { + // |logo_tracker_| owns |logo_cache_|, which gets destroyed on a background + // sequence after |logo_tracker_|s destruction. Ensure that |logo_cache_| is + // actually destroyed before the test ends to make gmock happy. + logo_tracker_.reset(); + task_environment_.RunUntilIdle(); } // Returns the response that the server would send for the given logo. @@ -360,16 +358,16 @@ net::URLRequestStatus::SUCCESS, net::HttpStatusCode response_code = net::HTTP_OK); - // Calls logo_tracker_->GetLogo() with listener_ and waits for the + // Calls logo_tracker_->GetLogo() with |observer_| and waits for the // asynchronous response(s). void GetLogo(); - std::unique_ptr<base::MessageLoop> message_loop_; + base::test::ScopedTaskEnvironment task_environment_; GURL logo_url_; base::SimpleTestClock* test_clock_; NiceMock<MockLogoCache>* logo_cache_; net::FakeURLFetcherFactory fake_url_fetcher_factory_; - LogoTracker* logo_tracker_; + std::unique_ptr<LogoTracker> logo_tracker_; NiceMock<MockLogoObserver> observer_; }; @@ -401,7 +399,7 @@ void LogoTrackerTest::GetLogo() { logo_tracker_->GetLogo(&observer_); - base::RunLoop().RunUntilIdle(); + task_environment_.RunUntilIdle(); } // Tests ----------------------------------------------------------------------- @@ -441,18 +439,18 @@ TEST_F(LogoTrackerTest, EmptyCacheAndFailedDownload) { EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0); EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0); - EXPECT_CALL(*logo_cache_, SetCachedLogo(NULL)).Times(AnyNumber()); + EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber()); SetServerResponse("server is borked"); - observer_.ExpectCachedLogo(NULL); + observer_.ExpectCachedLogo(nullptr); GetLogo(); SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK); - observer_.ExpectCachedLogo(NULL); + observer_.ExpectCachedLogo(nullptr); GetLogo(); SetServerResponse("", net::URLRequestStatus::SUCCESS, net::HTTP_BAD_GATEWAY); - observer_.ExpectCachedLogo(NULL); + observer_.ExpectCachedLogo(nullptr); GetLogo(); } @@ -506,7 +504,7 @@ observer_.ExpectCachedLogo(&cached_logo); GetLogo(); - EXPECT_TRUE(logo_cache_->GetCachedLogoMetadata() != NULL); + ASSERT_TRUE(logo_cache_->GetCachedLogoMetadata()); EXPECT_EQ(fresh_logo.metadata.expiration_time, logo_cache_->GetCachedLogoMetadata()->expiration_time); @@ -571,10 +569,10 @@ SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, ")]}' {\"update\":{}}"); - logo_cache_->ExpectSetCachedLogo(NULL); + logo_cache_->ExpectSetCachedLogo(nullptr); EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0); EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1)); - observer_.ExpectCachedAndFreshLogos(&cached_logo, NULL); + observer_.ExpectCachedAndFreshLogos(&cached_logo, nullptr); GetLogo(); } @@ -587,9 +585,9 @@ EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0); EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0); - EXPECT_CALL(*logo_cache_, SetCachedLogo(NULL)).Times(AnyNumber()); + EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber()); EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1)); - observer_.ExpectCachedLogo(NULL); + observer_.ExpectCachedLogo(nullptr); GetLogo(); } @@ -602,7 +600,7 @@ const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata(); - EXPECT_TRUE(cached_metadata != NULL); + ASSERT_TRUE(cached_metadata); EXPECT_FALSE(cached_metadata->can_show_after_expiration); EXPECT_EQ(test_clock_->Now() + time_to_live, cached_metadata->expiration_time); @@ -616,7 +614,7 @@ const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata(); - EXPECT_TRUE(cached_metadata != NULL); + ASSERT_TRUE(cached_metadata); EXPECT_TRUE(cached_metadata->can_show_after_expiration); EXPECT_EQ(test_clock_->Now() + base::TimeDelta::FromDays(30), cached_metadata->expiration_time); @@ -665,9 +663,9 @@ EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0); EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0); - EXPECT_CALL(*logo_cache_, SetCachedLogo(NULL)).Times(AnyNumber()); + EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber()); EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1)); - observer_.ExpectCachedLogo(NULL); + observer_.ExpectCachedLogo(nullptr); GetLogo(); } @@ -681,9 +679,9 @@ EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0); EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0); - EXPECT_CALL(*logo_cache_, SetCachedLogo(NULL)).Times(AnyNumber()); + EXPECT_CALL(*logo_cache_, SetCachedLogo(nullptr)).Times(AnyNumber()); EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1)); - observer_.ExpectCachedLogo(NULL); + observer_.ExpectCachedLogo(nullptr); GetLogo(); } @@ -715,16 +713,16 @@ const int kNumListeners = 10; std::vector<std::unique_ptr<MockLogoObserver>> listeners; for (int i = 0; i < kNumListeners; ++i) { - MockLogoObserver* listener = new MockLogoObserver(); + auto listener = base::MakeUnique<MockLogoObserver>(); listener->ExpectCachedAndFreshLogos(&cached_logo, &fresh_logo); - listeners.push_back(base::WrapUnique(listener)); + listeners.push_back(std::move(listener)); } - EnqueueObservers(logo_tracker_, listeners, 0); + EnqueueObservers(logo_tracker_.get(), listeners, 0); EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(AtMost(3)); EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(3)); - base::RunLoop().RunUntilIdle(); + task_environment_.RunUntilIdle(); } TEST_F(LogoTrackerTest, DeleteObserversWhenLogoURLChanged) { @@ -743,7 +741,7 @@ listener2.ExpectFreshLogo(&logo); logo_tracker_->GetLogo(&listener2); - base::RunLoop().RunUntilIdle(); + task_environment_.RunUntilIdle(); } } // namespace
diff --git a/components/signin/core/browser/fake_signin_manager.h b/components/signin/core/browser/fake_signin_manager.h index e0168754..b3943e0 100644 --- a/components/signin/core/browser/fake_signin_manager.h +++ b/components/signin/core/browser/fake_signin_manager.h
@@ -13,9 +13,7 @@ #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_metrics.h" -// SigninManager to use for testing. Tests should use the type -// SigninManagerForTesting to ensure that the right type for their platform is -// used. +// SigninManager to use for testing. class FakeSigninManagerBase : public SigninManagerBase { public: @@ -44,7 +42,7 @@ void set_password(const std::string& password) { password_ = password; } - void SignIn(const std::string& account_id, + void SignIn(const std::string& gaia_id, const std::string& username, const std::string& password);
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc index 8eb3dcc..9f490a1 100644 --- a/components/sync/test/fake_server/fake_server.cc +++ b/components/sync/test/fake_server/fake_server.cc
@@ -401,13 +401,20 @@ return id; } +void FakeServer::OverrideResponseType( + ResponseTypeProvider response_type_override) { + response_type_override_ = std::move(response_type_override); +} + void FakeServer::BuildEntryResponseForSuccessfulCommit( const std::string& entity_id, sync_pb::CommitResponse_EntryResponse* entry_response) { EntityMap::const_iterator iter = entities_.find(entity_id); CHECK(iter != entities_.end()); const FakeServerEntity& entity = *iter->second; - entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS); + entry_response->set_response_type(response_type_override_ + ? response_type_override_.Run(entity) + : sync_pb::CommitResponse::SUCCESS); entry_response->set_id_string(entity.id()); if (entity.IsDeleted()) {
diff --git a/components/sync/test/fake_server/fake_server.h b/components/sync/test/fake_server/fake_server.h index b37a00c..9cd8ed5 100644 --- a/components/sync/test/fake_server/fake_server.h +++ b/components/sync/test/fake_server/fake_server.h
@@ -146,6 +146,18 @@ // Returns the current FakeServer as a WeakPtr. base::WeakPtr<FakeServer> AsWeakPtr(); + using ResponseTypeProvider = + base::RepeatingCallback<sync_pb::CommitResponse::ResponseType( + const FakeServerEntity& entity)>; + + // Use this callback to generate response types for entities. They will still + // be "committed" and stored as normal, this only affects the response type + // the client sees. This allows tests to still inspect what the client has + // done, although not as useful of a mechanism for multi client tests. Care + // should be taken when failing responses, as the client will go into + // exponential backoff, which can cause tests to be slow or time out. + void OverrideResponseType(ResponseTypeProvider response_type_override); + private: using EntityMap = std::map<std::string, std::unique_ptr<FakeServerEntity>>; @@ -255,6 +267,8 @@ sync_pb::ClientToServerMessage last_commit_message_; sync_pb::ClientToServerMessage last_getupdates_message_; + ResponseTypeProvider response_type_override_; + // Used to verify that FakeServer is only used from one thread. base::ThreadChecker thread_checker_;
diff --git a/components/update_client/background_downloader_win.cc b/components/update_client/background_downloader_win.cc index f82dc1c..fd391de 100644 --- a/components/update_client/background_downloader_win.cc +++ b/components/update_client/background_downloader_win.cc
@@ -24,6 +24,7 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string_piece.h" #include "base/strings/sys_string_conversions.h" #include "base/win/scoped_co_mem.h" #include "components/update_client/utils.h" @@ -320,52 +321,29 @@ return jobs->empty() ? S_FALSE : S_OK; } -// Compares the job creation time and returns true if the job creation time -// is older than |num_days|. -class JobCreationOlderThanDays { - public: - explicit JobCreationOlderThanDays(int num_days) : num_days_(num_days) {} - bool operator()(const ComPtr<IBackgroundCopyJob>& job) const; - - private: - int num_days_; -}; - -bool JobCreationOlderThanDays::operator()( - const ComPtr<IBackgroundCopyJob>& job) const { +bool JobCreationOlderThanDaysPredicate(ComPtr<IBackgroundCopyJob> job, + int num_days) { BG_JOB_TIMES times = {}; HRESULT hr = job->GetTimes(×); if (FAILED(hr)) return false; - const base::TimeDelta time_delta(base::TimeDelta::FromDays(num_days_)); + const base::TimeDelta time_delta(base::TimeDelta::FromDays(num_days)); const base::Time creation_time(base::Time::FromFileTime(times.CreationTime)); return creation_time + time_delta < base::Time::Now(); } -// Compares the url of a file in a job and returns true if the remote name -// of any file in a job matches the argument. -class JobFileUrlEqual { - public: - explicit JobFileUrlEqual(const base::string16& remote_name) - : remote_name_(remote_name) {} - bool operator()(const ComPtr<IBackgroundCopyJob>& job) const; - - private: - base::string16 remote_name_; -}; - -bool JobFileUrlEqual::operator()(const ComPtr<IBackgroundCopyJob>& job) const { +bool JobFileUrlEqualPredicate(ComPtr<IBackgroundCopyJob> job, const GURL& url) { std::vector<ComPtr<IBackgroundCopyFile>> files; HRESULT hr = GetFilesInJob(job, &files); if (FAILED(hr)) return false; for (size_t i = 0; i != files.size(); ++i) { - ScopedCoMem<base::char16> name; - if (SUCCEEDED(files[i]->GetRemoteName(&name)) && - remote_name_.compare(name) == 0) + ScopedCoMem<base::char16> remote_name; + if (SUCCEEDED(files[i]->GetRemoteName(&remote_name)) && + url == GURL(base::StringPiece16(remote_name))) return true; } @@ -426,8 +404,11 @@ last_sweep = current_time; std::vector<ComPtr<IBackgroundCopyJob>> jobs; - HRESULT hr = FindBitsJobIf(JobCreationOlderThanDays(kPurgeStaleJobsAfterDays), - bits_manager, &jobs); + HRESULT hr = FindBitsJobIf( + std::bind2nd(std::ptr_fun(JobCreationOlderThanDaysPredicate), + kPurgeStaleJobsAfterDays), + bits_manager, &jobs); + if (FAILED(hr)) return hr; @@ -766,8 +747,9 @@ HRESULT BackgroundDownloader::CreateOrOpenJob(const GURL& url, ComPtr<IBackgroundCopyJob>* job) { std::vector<ComPtr<IBackgroundCopyJob>> jobs; - HRESULT hr = FindBitsJobIf(JobFileUrlEqual(base::SysUTF8ToWide(url.spec())), - bits_manager_, &jobs); + HRESULT hr = + FindBitsJobIf(std::bind2nd(std::ptr_fun(JobFileUrlEqualPredicate), url), + bits_manager_, &jobs); if (SUCCEEDED(hr) && !jobs.empty()) { *job = jobs.front(); return hr;
diff --git a/components/viz/DEPS b/components/viz/DEPS deleted file mode 100644 index f8654e9ef..0000000 --- a/components/viz/DEPS +++ /dev/null
@@ -1,4 +0,0 @@ -include_rules = [ - "+gpu", - "+mojo/public", -]
diff --git a/components/viz/client/DEPS b/components/viz/client/DEPS index 86ba24d6..3450aad8 100644 --- a/components/viz/client/DEPS +++ b/components/viz/client/DEPS
@@ -1,4 +1,9 @@ include_rules = [ "+cc", + "-cc/blink", + "-cc/test", + + "+mojo/public/cpp/bindings", + "+mojo/public/cpp/system", "+ui/gfx/geometry", ]
diff --git a/components/viz/common/DEPS b/components/viz/common/DEPS index 6df009f..2455aca 100644 --- a/components/viz/common/DEPS +++ b/components/viz/common/DEPS
@@ -1,16 +1,22 @@ -include_rules = [ - "+ui/gfx/geometry", - "+services/ui/gpu/interfaces", - "+third_party/skia", -] - specific_include_rules = { + # DEPS for GLHelper and friends which are in the root common/ directory. + ".*\.(cc|h)": [ + "+gpu/GLES2", + "+gpu/command_buffer/client", + "+gpu/command_buffer/common", + "+gpu/ipc/common", + "+ui/gfx/geometry", + "+services/ui/gpu/interfaces", + "+third_party/skia", + ], ".*_unittest\.cc": [ + "+gpu/ipc/gl_in_process_context.h", "+media/base", "+ui/gfx", "+ui/gl", ], ".*_benchmark\.cc": [ + "+gpu/ipc/gl_in_process_context.h", "+ui/gfx", ], }
diff --git a/components/viz/host/DEPS b/components/viz/host/DEPS index c4eca43..b4d33612 100644 --- a/components/viz/host/DEPS +++ b/components/viz/host/DEPS
@@ -1,6 +1,12 @@ include_rules = [ "+cc/ipc", "+cc/surfaces", + "+gpu/command_buffer/client", + "+gpu/command_buffer/common", + "+gpu/ipc/client", + "+gpu/ipc/common", + "+gpu/ipc/host", + "+mojo/public/cpp/bindings", "+services/ui/gpu/interfaces", ]
diff --git a/components/viz/service/display_embedder/DEPS b/components/viz/service/display_embedder/DEPS index dba221e..f97559d 100644 --- a/components/viz/service/display_embedder/DEPS +++ b/components/viz/service/display_embedder/DEPS
@@ -11,6 +11,7 @@ "+gpu/command_buffer/service", "+gpu/ipc/client", "+gpu/ipc/common", + "+gpu/ipc/in_process_command_buffer.h", "+gpu/ipc/service", "+mojo/public/cpp/bindings", "+mojo/public/cpp/system",
diff --git a/components/viz/service/frame_sinks/DEPS b/components/viz/service/frame_sinks/DEPS index de07c6b..8e8b659 100644 --- a/components/viz/service/frame_sinks/DEPS +++ b/components/viz/service/frame_sinks/DEPS
@@ -4,4 +4,6 @@ "+cc/surfaces", "+cc/scheduler", "+components/viz/display_embedder", + "+gpu/ipc/common", + "+mojo/public/cpp/bindings", ]
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc index 121c13e..0f82baf 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -24,12 +24,12 @@ : cc::SurfaceManager::LifetimeType::SEQUENCES), display_provider_(display_provider), binding_(this) { - manager_.AddObserver(this); + manager_.surface_manager()->AddObserver(this); } FrameSinkManagerImpl::~FrameSinkManagerImpl() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - manager_.RemoveObserver(this); + manager_.surface_manager()->RemoveObserver(this); } void FrameSinkManagerImpl::BindPtrAndSetClient(
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h index bf6102c..597b22c 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -14,7 +14,7 @@ #include "base/threading/thread_checker.h" #include "cc/ipc/frame_sink_manager.mojom.h" #include "cc/surfaces/frame_sink_id.h" -#include "cc/surfaces/surface_manager.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface_observer.h" #include "components/viz/service/frame_sinks/gpu_compositor_frame_sink_delegate.h" #include "components/viz/service/viz_service_export.h" @@ -42,7 +42,7 @@ DisplayProvider* display_provider); ~FrameSinkManagerImpl() override; - cc::SurfaceManager* surface_manager() { return &manager_; } + cc::FrameSinkManager* frame_sink_manager() { return &manager_; } // Binds |this| as a FrameSinkManager for a given |request|. This may // only be called once. @@ -93,10 +93,10 @@ void OnClientConnectionLost(const cc::FrameSinkId& frame_sink_id) override; void OnPrivateConnectionLost(const cc::FrameSinkId& frame_sink_id) override; - // SurfaceManager should be the first object constructed and the last object + // FrameSinkManager should be the first object constructed and the last object // destroyed in order to ensure that all other objects that depend on it have // access to a valid pointer for the entirety of their lifetimes. - cc::SurfaceManager manager_; + cc::FrameSinkManager manager_; // Provides a cc::Display for CreateRootCompositorFrameSink(). DisplayProvider* const display_provider_;
diff --git a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc index 427cc86..6a75a191 100644 --- a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc +++ b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc
@@ -10,7 +10,7 @@ GpuCompositorFrameSink::GpuCompositorFrameSink( GpuCompositorFrameSinkDelegate* delegate, - cc::SurfaceManager* surface_manager, + cc::FrameSinkManager* frame_sink_manager, const cc::FrameSinkId& frame_sink_id, cc::mojom::CompositorFrameSinkRequest request, cc::mojom::CompositorFrameSinkPrivateRequest @@ -19,7 +19,7 @@ : delegate_(delegate), support_(cc::CompositorFrameSinkSupport::Create( this, - surface_manager, + frame_sink_manager, frame_sink_id, false /* is_root */, true /* handles_frame_sink_id_invalidation */,
diff --git a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h index b711cec..24a6ad2 100644 --- a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h +++ b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h
@@ -28,7 +28,7 @@ public: GpuCompositorFrameSink( GpuCompositorFrameSinkDelegate* delegate, - cc::SurfaceManager* surface_manager, + cc::FrameSinkManager* frame_sink_manager, const cc::FrameSinkId& frame_sink_id, cc::mojom::CompositorFrameSinkRequest request, cc::mojom::CompositorFrameSinkPrivateRequest private_request,
diff --git a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc index bb04a8f..26ad063 100644 --- a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc +++ b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc
@@ -8,12 +8,13 @@ #include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/display.h" +#include "cc/surfaces/frame_sink_manager.h" namespace viz { GpuRootCompositorFrameSink::GpuRootCompositorFrameSink( GpuCompositorFrameSinkDelegate* delegate, - cc::SurfaceManager* surface_manager, + cc::FrameSinkManager* frame_sink_manager, const cc::FrameSinkId& frame_sink_id, std::unique_ptr<cc::Display> display, std::unique_ptr<cc::BeginFrameSource> begin_frame_source, @@ -25,7 +26,7 @@ : delegate_(delegate), support_(cc::CompositorFrameSinkSupport::Create( this, - surface_manager, + frame_sink_manager, frame_sink_id, true /* is_root */, true /* handles_frame_sink_id_invalidation */, @@ -45,13 +46,13 @@ compositor_frame_sink_private_binding_.set_connection_error_handler( base::Bind(&GpuRootCompositorFrameSink::OnPrivateConnectionLost, base::Unretained(this))); - surface_manager->RegisterBeginFrameSource(display_begin_frame_source_.get(), - frame_sink_id); - display_->Initialize(this, surface_manager); + frame_sink_manager->RegisterBeginFrameSource( + display_begin_frame_source_.get(), frame_sink_id); + display_->Initialize(this, frame_sink_manager->surface_manager()); } GpuRootCompositorFrameSink::~GpuRootCompositorFrameSink() { - support_->surface_manager()->UnregisterBeginFrameSource( + support_->frame_sink_manager()->UnregisterBeginFrameSource( display_begin_frame_source_.get()); }
diff --git a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h index aee3e1ea..6d28a2f 100644 --- a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h +++ b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h
@@ -21,7 +21,7 @@ class BeginFrameSource; class CompositorFrameSinkSupport; class Display; -class SurfaceManager; +class FrameSinkManager; } namespace viz { @@ -37,7 +37,7 @@ public: GpuRootCompositorFrameSink( GpuCompositorFrameSinkDelegate* delegate, - cc::SurfaceManager* surface_manager, + cc::FrameSinkManager* frame_sink_manager, const cc::FrameSinkId& frame_sink_id, std::unique_ptr<cc::Display> display, std::unique_ptr<cc::BeginFrameSource> begin_frame_source,
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 06f8106..99d26e5 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -128,6 +128,11 @@ return false; } +bool BrowserAccessibility::IsDocument() const { + return GetRole() == ui::AX_ROLE_ROOT_WEB_AREA || + GetRole() == ui::AX_ROLE_WEB_AREA; +} + bool BrowserAccessibility::IsTextOnlyObject() const { return GetRole() == ui::AX_ROLE_STATIC_TEXT || GetRole() == ui::AX_ROLE_LINE_BREAK || @@ -958,6 +963,14 @@ return html_tag == "textarea"; } +// In general we should use IsEditField() instead if we want to check for +// something that has a caret and the user can edit. +// TODO(aleventhal) this name is confusing because it returns true for combobox, +// and we should take a look at why a combobox is considered a text control. The +// ARIA spec says a combobox would contain (but not be) a text field. It looks +// like a mistake may have been made in that comboboxes have been considered a +// kind of textbox. Find an appropriate name for this function, and consider +// returning false for comboboxes it doesn't break existing websites. bool BrowserAccessibility::IsSimpleTextControl() const { // Time fields, color wells and spinner buttons might also use text fields as // constituent parts, but they are not considered text fields as a whole. @@ -972,6 +985,11 @@ } } +bool BrowserAccessibility::IsEditField() const { + return GetRole() == ui::AX_ROLE_TEXT_FIELD || + GetRole() == ui::AX_ROLE_SEARCH_BOX; +} + // Indicates if this object is at the root of a rich edit text control. bool BrowserAccessibility::IsRichTextControl() const { return HasState(ui::AX_STATE_RICHLY_EDITABLE) &&
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index b7a098d..6716a2e 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h
@@ -99,6 +99,10 @@ // Return true if this object is equal to or a descendant of |ancestor|. bool IsDescendantOf(const BrowserAccessibility* ancestor) const; + bool IsDocument() const; + + bool IsEditField() const; + // Returns true if this object is used only for representing text. bool IsTextOnlyObject() const;
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc index 809a6ce4..57ff9025 100644 --- a/content/browser/accessibility/browser_accessibility_com_win.cc +++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -2851,8 +2851,7 @@ *num_children = owner()->PlatformChildCount(); *unique_id = -owner()->unique_id(); - if (owner()->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA || - owner()->GetRole() == ui::AX_ROLE_WEB_AREA) { + if (owner()->IsDocument()) { *node_type = NODETYPE_DOCUMENT; } else if (owner()->IsTextOnlyObject()) { *node_type = NODETYPE_TEXT; @@ -3696,8 +3695,7 @@ win_attributes_->ia2_attributes.push_back(L"valuetext:" + value); } else { // On Windows, the value of a document should be its url. - if (owner()->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA || - owner()->GetRole() == ui::AX_ROLE_WEB_AREA) { + if (owner()->IsDocument()) { value = base::UTF8ToUTF16(Manager()->GetTreeData().url); } // If this doesn't have a value and is linked then set its value to the url @@ -4944,9 +4942,22 @@ if (owner()->HasState(ui::AX_STATE_HORIZONTAL)) ia2_state |= IA2_STATE_HORIZONTAL; - if (owner()->HasState(ui::AX_STATE_EDITABLE)) + const bool is_editable = owner()->HasState(ui::AX_STATE_EDITABLE); + if (is_editable) ia2_state |= IA2_STATE_EDITABLE; + if (owner()->IsRichTextControl() || owner()->IsEditField()) { + // Support multi/single line states if root editable or appropriate role. + // We support the edit box roles even if the area is not actually editable, + // because it is technically feasible for JS to implement the edit box + // by controlling selection. + if (owner()->HasState(ui::AX_STATE_MULTILINE)) { + ia2_state |= IA2_STATE_MULTI_LINE; + } else { + ia2_state |= IA2_STATE_SINGLE_LINE; + } + } + if (!owner()->GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty()) ia2_state |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; @@ -5319,11 +5330,6 @@ case ui::AX_ROLE_TEXT_FIELD: case ui::AX_ROLE_SEARCH_BOX: ia_role = ROLE_SYSTEM_TEXT; - if (owner()->HasState(ui::AX_STATE_MULTILINE)) { - ia2_state |= IA2_STATE_MULTI_LINE; - } else { - ia2_state |= IA2_STATE_SINGLE_LINE; - } ia2_state |= IA2_STATE_SELECTABLE_TEXT; break; case ui::AX_ROLE_ABBR:
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 34484feb..da028936 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -198,7 +198,7 @@ AddFilter(filters, "haspopup"); AddFilter(filters, "horizontal"); AddFilter(filters, "invisible"); - // TODO(aleventhal) multiline + AddFilter(filters, "multiline"); AddFilter(filters, "multiselectable"); AddFilter(filters, "protected"); // TODO(aleventhal) Add readonly support back after control mode refactor
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 6e9ddad..be8eddc 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1215,7 +1215,7 @@ #if !defined(OS_ANDROID) host_frame_sink_manager_.reset(); - frame_sink_manager_.reset(); + frame_sink_manager_impl_.reset(); #endif // The device monitors are using |system_monitor_| as dependency, so delete @@ -1361,8 +1361,8 @@ } #if !defined(OS_ANDROID) -cc::SurfaceManager* BrowserMainLoop::GetSurfaceManager() const { - return frame_sink_manager_->surface_manager(); +cc::FrameSinkManager* BrowserMainLoop::GetFrameSinkManager() const { + return frame_sink_manager_impl_->frame_sink_manager(); } #endif @@ -1452,7 +1452,7 @@ } #if !defined(OS_ANDROID) if (!service_manager::ServiceManagerIsRemote()) { - frame_sink_manager_ = + frame_sink_manager_impl_ = base::MakeUnique<viz::FrameSinkManagerImpl>(false, nullptr); host_frame_sink_manager_ = base::MakeUnique<viz::HostFrameSinkManager>(); @@ -1460,7 +1460,7 @@ // TODO(danakj): Don't make a FrameSinkManagerImpl when display is in the // Gpu process, instead get the mojo pointer from the Gpu process. surface_utils::ConnectWithInProcessFrameSinkManager( - host_frame_sink_manager_.get(), frame_sink_manager_.get()); + host_frame_sink_manager_.get(), frame_sink_manager_impl_.get()); } #endif
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index 7b72970..2a076b2 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -36,7 +36,7 @@ } // namespace base namespace cc { -class SurfaceManager; +class FrameSinkManager; } namespace discardable_memory { @@ -189,7 +189,7 @@ // TODO(crbug.com/657959): This will be removed once there are no users, as // SurfaceManager is being moved out of process. - cc::SurfaceManager* GetSurfaceManager() const; + cc::FrameSinkManager* GetFrameSinkManager() const; #endif void StopStartupTracingTimer(); @@ -362,7 +362,7 @@ // access to |in_process_frame_sink_manager_| should happen via // |host_frame_sink_manager_| instead which uses Mojo. See // http://crbug.com/657959. - std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_; + std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl_; #endif // DO NOT add members here. Add them to the right categories above.
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 4889010..30cc0ed 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -15,9 +15,9 @@ #include "base/pickle.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_info.h" -#include "cc/surfaces/surface_manager.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/child_process_security_policy_impl.h" @@ -440,14 +440,14 @@ void BrowserPluginGuest::OnSatisfySequence( int instance_id, const cc::SurfaceSequence& sequence) { - GetSurfaceManager()->SatisfySequence(sequence); + GetFrameSinkManager()->surface_manager()->SatisfySequence(sequence); } void BrowserPluginGuest::OnRequireSequence( int instance_id, const cc::SurfaceId& id, const cc::SurfaceSequence& sequence) { - GetSurfaceManager()->RequireSequence(id, sequence); + GetFrameSinkManager()->surface_manager()->RequireSequence(id, sequence); } void BrowserPluginGuest::ResendEventToEmbedder(
diff --git a/content/browser/child_process_launcher_helper_posix.cc b/content/browser/child_process_launcher_helper_posix.cc index 9b2f6e0fc..38b818d 100644 --- a/content/browser/child_process_launcher_helper_posix.cc +++ b/content/browser/child_process_launcher_helper_posix.cc
@@ -115,7 +115,8 @@ base::PlatformFile file = OpenFileIfNecessary(key_path_iter.second, ®ion); if (file == base::kInvalidPlatformFile) { - DLOG(ERROR) << "Ignoring invalid file " << key_path_iter.second.value(); + DLOG(WARNING) << "Ignoring invalid file " + << key_path_iter.second.value(); continue; } file_switch_value_builder.AddEntry(key_path_iter.first, key);
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 59c85d93..19b47d9 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -29,7 +29,7 @@ #include "cc/surfaces/direct_layer_tree_frame_sink.h" #include "cc/surfaces/display.h" #include "cc/surfaces/display_scheduler.h" -#include "cc/surfaces/surface_manager.h" +#include "cc/surfaces/frame_sink_manager.h" #include "components/viz/common/gl_helper.h" #include "components/viz/host/host_frame_sink_manager.h" #include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h" @@ -591,10 +591,10 @@ compositor->widget()); #endif if (data->synthetic_begin_frame_source) { - GetSurfaceManager()->UnregisterBeginFrameSource( + GetFrameSinkManager()->UnregisterBeginFrameSource( data->synthetic_begin_frame_source.get()); } else if (data->gpu_vsync_begin_frame_source) { - GetSurfaceManager()->UnregisterBeginFrameSource( + GetFrameSinkManager()->UnregisterBeginFrameSource( data->gpu_vsync_begin_frame_source.get()); } @@ -609,8 +609,8 @@ std::move(display_output_surface), std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>( compositor->task_runner().get())); - GetSurfaceManager()->RegisterBeginFrameSource(begin_frame_source, - compositor->frame_sink_id()); + GetFrameSinkManager()->RegisterBeginFrameSource(begin_frame_source, + compositor->frame_sink_id()); // Note that we are careful not to destroy prior BeginFrameSource objects // until we have reset |data->display|. data->synthetic_begin_frame_source = std::move(synthetic_begin_frame_source); @@ -622,12 +622,12 @@ auto layer_tree_frame_sink = vulkan_context_provider ? base::MakeUnique<cc::DirectLayerTreeFrameSink>( - compositor->frame_sink_id(), GetSurfaceManager(), + compositor->frame_sink_id(), GetFrameSinkManager(), data->display.get(), static_cast<scoped_refptr<cc::VulkanContextProvider>>( vulkan_context_provider)) : base::MakeUnique<cc::DirectLayerTreeFrameSink>( - compositor->frame_sink_id(), GetSurfaceManager(), + compositor->frame_sink_id(), GetFrameSinkManager(), data->display.get(), context_provider, shared_worker_context_provider_, GetGpuMemoryBufferManager(), viz::ServerSharedBitmapManager::current()); @@ -671,10 +671,10 @@ gpu::GpuSurfaceTracker::Get()->RemoveSurface(data->surface_handle); #endif if (data->synthetic_begin_frame_source) { - GetSurfaceManager()->UnregisterBeginFrameSource( + GetFrameSinkManager()->UnregisterBeginFrameSource( data->synthetic_begin_frame_source.get()); } else if (data->gpu_vsync_begin_frame_source) { - GetSurfaceManager()->UnregisterBeginFrameSource( + GetFrameSinkManager()->UnregisterBeginFrameSource( data->gpu_vsync_begin_frame_source.get()); } per_compositor_data_.erase(it); @@ -727,10 +727,6 @@ return frame_sink_id_allocator_.NextFrameSinkId(); } -cc::SurfaceManager* GpuProcessTransportFactory::GetSurfaceManager() { - return BrowserMainLoop::GetInstance()->GetSurfaceManager(); -} - viz::HostFrameSinkManager* GpuProcessTransportFactory::GetHostFrameSinkManager() { return BrowserMainLoop::GetInstance()->host_frame_sink_manager(); @@ -831,6 +827,10 @@ observer_list_.RemoveObserver(observer); } +cc::FrameSinkManager* GpuProcessTransportFactory::GetFrameSinkManager() { + return BrowserMainLoop::GetInstance()->GetFrameSinkManager(); +} + viz::GLHelper* GpuProcessTransportFactory::GetGLHelper() { if (!gl_helper_ && !per_compositor_data_.empty()) { scoped_refptr<cc::ContextProvider> provider =
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h index d9c0b77..7c17eb8d 100644 --- a/content/browser/compositor/gpu_process_transport_factory.h +++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -63,7 +63,6 @@ void RemoveReflector(ui::Reflector* reflector) override; void RemoveCompositor(ui::Compositor* compositor) override; cc::FrameSinkId AllocateFrameSinkId() override; - cc::SurfaceManager* GetSurfaceManager() override; viz::HostFrameSinkManager* GetHostFrameSinkManager() override; void SetDisplayVisible(ui::Compositor* compositor, bool visible) override; void ResizeDisplay(ui::Compositor* compositor, @@ -81,6 +80,7 @@ // ImageTransportFactory implementation. ui::ContextFactory* GetContextFactory() override; ui::ContextFactoryPrivate* GetContextFactoryPrivate() override; + cc::FrameSinkManager* GetFrameSinkManager() override; viz::GLHelper* GetGLHelper() override; void SetGpuChannelEstablishFactory( gpu::GpuChannelEstablishFactory* factory) override;
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc index 04184659..185d48d 100644 --- a/content/browser/compositor/surface_utils.cc +++ b/content/browser/compositor/surface_utils.cc
@@ -164,14 +164,14 @@ #endif } -cc::SurfaceManager* GetSurfaceManager() { +cc::FrameSinkManager* GetFrameSinkManager() { #if defined(OS_ANDROID) - return CompositorImpl::GetSurfaceManager(); + return CompositorImpl::GetFrameSinkManager(); #else ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); if (factory == NULL) return nullptr; - return factory->GetContextFactoryPrivate()->GetSurfaceManager(); + return factory->GetContextFactoryPrivate()->GetFrameSinkManager(); #endif }
diff --git a/content/browser/compositor/surface_utils.h b/content/browser/compositor/surface_utils.h index cf6a677..3a4c680a2 100644 --- a/content/browser/compositor/surface_utils.h +++ b/content/browser/compositor/surface_utils.h
@@ -15,7 +15,7 @@ namespace cc { class CopyOutputResult; -class SurfaceManager; +class FrameSinkManager; } // namespace cc namespace viz { @@ -27,7 +27,7 @@ CONTENT_EXPORT cc::FrameSinkId AllocateFrameSinkId(); -CONTENT_EXPORT cc::SurfaceManager* GetSurfaceManager(); +CONTENT_EXPORT cc::FrameSinkManager* GetFrameSinkManager(); CONTENT_EXPORT viz::HostFrameSinkManager* GetHostFrameSinkManager();
diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.cc b/content/browser/compositor/test/no_transport_image_transport_factory.cc index 8581cbe0..03f857eb 100644 --- a/content/browser/compositor/test/no_transport_image_transport_factory.cc +++ b/content/browser/compositor/test/no_transport_image_transport_factory.cc
@@ -20,7 +20,7 @@ NoTransportImageTransportFactory::NoTransportImageTransportFactory() : frame_sink_manager_(false /* use surface references */, nullptr), context_factory_(&host_frame_sink_manager_, - frame_sink_manager_.surface_manager()) { + frame_sink_manager_.frame_sink_manager()) { surface_utils::ConnectWithInProcessFrameSinkManager(&host_frame_sink_manager_, &frame_sink_manager_);
diff --git a/content/browser/devtools/devtools_url_request_interceptor.h b/content/browser/devtools/devtools_url_request_interceptor.h index cfd139a..e209149 100644 --- a/content/browser/devtools/devtools_url_request_interceptor.h +++ b/content/browser/devtools/devtools_url_request_interceptor.h
@@ -27,7 +27,7 @@ // An interceptor that creates DevToolsURLInterceptorRequestJobs for requests // from pages where interception has been enabled via -// Network.enableRequestInterception. +// Network.setRequestInterceptionEnabled. class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor { public: explicit DevToolsURLRequestInterceptor(BrowserContext* browser_context);
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index e5a831c..0891103 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -508,7 +508,7 @@ Response NetworkHandler::Disable() { enabled_ = false; user_agent_ = std::string(); - EnableRequestInterception(false); + SetRequestInterceptionEnabled(false); return Response::FallThrough(); } @@ -826,7 +826,7 @@ return enabled_ ? user_agent_ : std::string(); } -DispatchResponse NetworkHandler::EnableRequestInterception(bool enabled) { +DispatchResponse NetworkHandler::SetRequestInterceptionEnabled(bool enabled) { if (interception_enabled_ == enabled) return Response::OK(); // Nothing to do.
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h index 2f450db2..f0d64c93 100644 --- a/content/browser/devtools/protocol/network_handler.h +++ b/content/browser/devtools/protocol/network_handler.h
@@ -70,7 +70,7 @@ Response SetUserAgentOverride(const std::string& user_agent) override; Response CanEmulateNetworkConditions(bool* result) override; - DispatchResponse EnableRequestInterception(bool enabled) override; + DispatchResponse SetRequestInterceptionEnabled(bool enabled) override; void ContinueInterceptedRequest( const std::string& request_id, Maybe<std::string> error_reason,
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index 5d58560..45e37cd 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -37,7 +37,7 @@ }, { "domain": "Network", - "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookie", "setCookie", "setUserAgentOverride", "canEmulateNetworkConditions", "enableRequestInterception", "continueInterceptedRequest"], + "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookie", "setCookie", "setUserAgentOverride", "canEmulateNetworkConditions", "setRequestInterceptionEnabled", "continueInterceptedRequest"], "include_types": ["CookieSameSite", "Cookie", "Response", "Headers", "Request", "ResourceTiming", "SecurityDetails", "SignedCertificateTimestamp", "Initiator", "ResourcePriority", "RequestWillBeSentNotification", "ResponseReceivedNotification", "LoadingFinishedNotification", "LoadingFailedNotification", "RequestWillBeSentNotification", "ErrorReason", "RequestInterceptedNotification", "AuthChallenge", "AuthChallengeResponse"], "include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted"],
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index dc42db7..fe36990 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -4,9 +4,9 @@ #include "content/browser/frame_host/cross_process_frame_connector.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_hittest.h" -#include "cc/surfaces/surface_manager.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/frame_host/frame_tree_node.h" @@ -97,13 +97,13 @@ void CrossProcessFrameConnector::OnSatisfySequence( const cc::SurfaceSequence& sequence) { - GetSurfaceManager()->SatisfySequence(sequence); + GetFrameSinkManager()->surface_manager()->SatisfySequence(sequence); } void CrossProcessFrameConnector::OnRequireSequence( const cc::SurfaceId& id, const cc::SurfaceSequence& sequence) { - GetSurfaceManager()->RequireSequence(id, sequence); + GetFrameSinkManager()->surface_manager()->RequireSequence(id, sequence); } gfx::Rect CrossProcessFrameConnector::ChildFrameRect() { @@ -139,7 +139,7 @@ // is necessary. *transformed_point = gfx::ConvertPointToPixel(view_->current_surface_scale_factor(), point); - cc::SurfaceHittest hittest(nullptr, GetSurfaceManager()); + cc::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager()); if (!hittest.TransformPointToTargetSurface(original_surface, local_surface_id, transformed_point)) return false;
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc index 96c4267..b25a6afd 100644 --- a/content/browser/frame_host/interstitial_page_impl.cc +++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -783,12 +783,14 @@ void InterstitialPageImpl::CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) { NOTREACHED() << "InterstitialPage does not support showing drop-downs."; } void InterstitialPageImpl::CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) { + int32_t route_id, + mojom::WidgetPtr widget) { NOTREACHED() << "InterstitialPage does not support showing full screen popups."; }
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h index cbab206..2550b95b 100644 --- a/content/browser/frame_host/interstitial_page_impl.h +++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -147,9 +147,11 @@ BrowserContext* browser_context) const override; void CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) override; void CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) override; + int32_t route_id, + mojom::WidgetPtr widget) override; void ShowCreatedWidget(int process_id, int route_id, const gfx::Rect& initial_rect) override;
diff --git a/content/browser/frame_host/navigator_delegate.cc b/content/browser/frame_host/navigator_delegate.cc index 6b067c50..786a58a 100644 --- a/content/browser/frame_host/navigator_delegate.cc +++ b/content/browser/frame_host/navigator_delegate.cc
@@ -30,4 +30,7 @@ return nullptr; } +void NavigatorDelegate::AdjustPreviewsStateForNavigation( + PreviewsState* previews_state) {} + } // namespace content
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h index 93a3e437..f632319f 100644 --- a/content/browser/frame_host/navigator_delegate.h +++ b/content/browser/frame_host/navigator_delegate.h
@@ -11,6 +11,7 @@ #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/navigation_ui_data.h" #include "content/public/browser/reload_type.h" +#include "content/public/common/previews_state.h" #include "ui/base/page_transition_types.h" #include "ui/base/window_open_disposition.h" @@ -131,6 +132,13 @@ // Whether the delegate is displaying an interstitial page over the current // page. virtual bool ShowingInterstitialPage() const = 0; + + // Gives the delegate a chance to adjust the previews state during navigation. + // When called, previews_state will be pointing to a valid set of previews, or + // an enum value disabling previews. The call will change the value of + // previews_state in place, and must change it to either a value disabling + // previews, or a subset of the previews passed in. + virtual void AdjustPreviewsStateForNavigation(PreviewsState* previews_state); }; } // namspace content
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index dd1dc184..297e8f0 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -369,6 +369,10 @@ previews_state = PREVIEWS_NO_TRANSFORM; } + // Give the delegate an opportunity to adjust the previews state. + if (delegate_) + delegate_->AdjustPreviewsStateForNavigation(&previews_state); + // PlzNavigate: the RenderFrameHosts are no longer asked to navigate. if (IsBrowserSideNavigationEnabled()) { navigation_data_.reset(new NavigationMetricsData(navigation_start, dest_url,
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc index f3d24295..83d5c86a 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -16,8 +16,10 @@ #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_manager.h" +#include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/browser_plugin/browser_plugin_guest.h" #include "content/browser/compositor/surface_utils.h" @@ -64,7 +66,7 @@ background_color_(SK_ColorWHITE), weak_factory_(this) { if (!service_manager::ServiceManagerIsRemote()) { - GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_); + GetFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_); CreateCompositorFrameSinkSupport(); } } @@ -72,8 +74,8 @@ RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() { if (!service_manager::ServiceManagerIsRemote()) { ResetCompositorFrameSinkSupport(); - if (GetSurfaceManager()) - GetSurfaceManager()->InvalidateFrameSinkId(frame_sink_id_); + if (GetFrameSinkManager()) + GetFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_); } } @@ -106,8 +108,8 @@ if (frame_connector_) { if (parent_frame_sink_id_.is_valid() && !service_manager::ServiceManagerIsRemote()) { - GetSurfaceManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_, - frame_sink_id_); + GetFrameSinkManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_, + frame_sink_id_); } parent_frame_sink_id_ = cc::FrameSinkId(); local_surface_id_ = cc::LocalSurfaceId(); @@ -124,8 +126,8 @@ parent_frame_sink_id_ = parent_view->GetFrameSinkId(); DCHECK(parent_frame_sink_id_.is_valid()); if (!service_manager::ServiceManagerIsRemote()) { - GetSurfaceManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_, - frame_sink_id_); + GetFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_, + frame_sink_id_); } } @@ -477,7 +479,7 @@ return; cc::SurfaceSequence sequence = cc::SurfaceSequence(frame_sink_id_, next_surface_sequence_++); - cc::SurfaceManager* manager = GetSurfaceManager(); + cc::SurfaceManager* manager = GetFrameSinkManager()->surface_manager(); cc::SurfaceId surface_id(frame_sink_id_, local_surface_id_); // The renderer process will satisfy this dependency when it creates a // SurfaceLayer. @@ -832,11 +834,11 @@ constexpr bool handles_frame_sink_id_invalidation = false; constexpr bool needs_sync_points = true; support_ = cc::CompositorFrameSinkSupport::Create( - this, GetSurfaceManager(), frame_sink_id_, is_root, + this, GetFrameSinkManager(), frame_sink_id_, is_root, handles_frame_sink_id_invalidation, needs_sync_points); if (parent_frame_sink_id_.is_valid()) { - GetSurfaceManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_, - frame_sink_id_); + GetFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_, + frame_sink_id_); } if (host_->needs_begin_frames()) support_->SetNeedsBeginFrame(true); @@ -846,8 +848,8 @@ if (!support_) return; if (parent_frame_sink_id_.is_valid()) { - GetSurfaceManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_, - frame_sink_id_); + GetFrameSinkManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_, + frame_sink_id_); } support_.reset(); }
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc index f85b047..3c53aef 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -205,8 +205,9 @@ if (id.is_valid()) { #if !defined(OS_ANDROID) ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - cc::SurfaceManager* manager = - factory->GetContextFactoryPrivate()->GetSurfaceManager(); + cc::SurfaceManager* manager = factory->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->surface_manager(); cc::Surface* surface = manager->GetSurfaceForId(id); EXPECT_TRUE(surface); // There should be a SurfaceSequence created by the RWHVChildFrame.
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc index 2e2a4cd0..4f21dc2 100644 --- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -265,7 +265,8 @@ #if !defined(OS_ANDROID) cc::SurfaceManager* manager = ImageTransportFactory::GetInstance() ->GetContextFactoryPrivate() - ->GetSurfaceManager(); + ->GetFrameSinkManager() + ->surface_manager(); cc::Surface* surface = manager->GetSurfaceForId(id); EXPECT_TRUE(surface); // There should be a SurfaceSequence created by the RWHVGuest.
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc index 1fe6c2b..c05fe38 100644 --- a/content/browser/loader/mojo_async_resource_handler_unittest.cc +++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -180,9 +180,9 @@ ADD_FAILURE() << "RequestComplete should not be called."; } - PreviewsState GetPreviewsState( - const net::URLRequest& url_request, - content::ResourceContext* resource_context) override { + PreviewsState GetPreviewsState(const net::URLRequest& url_request, + content::ResourceContext* resource_context, + PreviewsState previews_to_allow) override { ADD_FAILURE() << "GetPreviewsState should not be called."; return PREVIEWS_UNSPECIFIED; }
diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc index e328092..97044ed1 100644 --- a/content/browser/loader/resource_dispatcher_host_browsertest.cc +++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -647,7 +647,8 @@ PreviewsState GetPreviewsState( const net::URLRequest& request, - content::ResourceContext* resource_context) override { + content::ResourceContext* resource_context, + content::PreviewsState previews_to_allow) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); EXPECT_FALSE(should_get_previews_state_called_); should_get_previews_state_called_ = true;
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index f6d1b57..4080c66 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -132,7 +132,8 @@ namespace { constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = - net::DefineNetworkTrafficAnnotation("resource_dispather_host", R"( + net::DefineNetworkTrafficAnnotation("resource_dispather_host", + R"( semantics { sender: "Resource Dispatcher Host" description: @@ -247,14 +248,26 @@ // Returns the PreviewsState after requesting it from the delegate. The // PreviewsState is a bitmask of potentially several Previews optimizations. -PreviewsState GetPreviewsState(PreviewsState previews_state, +// If previews_to_allow is set to anything other than PREVIEWS_UNSPECIFIED, +// it is either the values passed in for a sub-frame to use, or if this is +// the main frame, it is a limitation on which previews to allow. +PreviewsState GetPreviewsState(PreviewsState previews_to_allow, ResourceDispatcherHostDelegate* delegate, const net::URLRequest& request, ResourceContext* resource_context, bool is_main_frame) { - // previews_state is set to PREVIEWS_OFF when reloading with Lo-Fi disabled. - if (previews_state == PREVIEWS_UNSPECIFIED && delegate && is_main_frame) - return delegate->GetPreviewsState(request, resource_context); + // If previews have already been turned off, or we are inheriting values on a + // sub-frame, don't check any further. + if (previews_to_allow & PREVIEWS_OFF || + previews_to_allow & PREVIEWS_NO_TRANSFORM || !is_main_frame || + !delegate) { + return previews_to_allow; + } + + // Get the mask of previews we could apply to the current navigation. + PreviewsState previews_state = + delegate->GetPreviewsState(request, resource_context, previews_to_allow); + return previews_state; } @@ -1385,6 +1398,14 @@ new_request->SetLoadFlags(load_flags); + // Update the previews state, but only if this is not using PlzNavigate. + PreviewsState previews_state = request_data.previews_state; + if (!IsBrowserSideNavigationEnabled()) { + previews_state = GetPreviewsState( + request_data.previews_state, delegate_, *new_request, resource_context, + request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME); + } + // Make extra info and read footer (contains request ID). ResourceRequestInfoImpl* extra_info = new ResourceRequestInfoImpl( requester_info, route_id, @@ -1399,12 +1420,10 @@ request_data.enable_load_timing, request_data.enable_upload_progress, do_not_prompt_for_login, request_data.referrer_policy, request_data.visibility_state, resource_context, report_raw_headers, - !is_sync_load, - GetPreviewsState(request_data.previews_state, delegate_, *new_request, - resource_context, - request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME), - request_data.request_body, request_data.initiated_in_secure_context); + !is_sync_load, previews_state, request_data.request_body, + request_data.initiated_in_secure_context); extra_info->SetBlobHandles(std::move(blob_handles)); + // Request takes ownership. extra_info->AssociateWithRequest(new_request.get()); @@ -2123,6 +2142,10 @@ BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get())); } + PreviewsState previews_state = + GetPreviewsState(info.common_params.previews_state, delegate_, + *new_request, resource_context, info.is_main_frame); + // Make extra info and read footer (contains request ID). // // TODO(davidben): Associate the request with the FrameTreeNode and/or tab so @@ -2151,9 +2174,7 @@ info.common_params.referrer.policy, info.page_visibility_state, resource_context, info.report_raw_headers, true, // is_async - GetPreviewsState(info.common_params.previews_state, delegate_, - *new_request, resource_context, info.is_main_frame), - info.common_params.post_data, + previews_state, info.common_params.post_data, // TODO(mek): Currently initiated_in_secure_context is only used for // subresource requests, so it doesn't matter what value it gets here. // If in the future this changes this should be updated to somehow get a
diff --git a/content/browser/media/android/media_resource_getter_impl.cc b/content/browser/media/android/media_resource_getter_impl.cc index f103e435..05ff22c 100644 --- a/content/browser/media/android/media_resource_getter_impl.cc +++ b/content/browser/media/android/media_resource_getter_impl.cc
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "base/path_service.h" #include "base/task_scheduler/post_task.h" -#include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/fileapi/browser_file_system_helper.h" #include "content/browser/resource_context_impl.h" @@ -29,10 +28,6 @@ #include "net/http/http_transaction_factory.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" -#include "storage/browser/blob/blob_data_handle.h" -#include "storage/browser/blob/blob_data_item.h" -#include "storage/browser/blob/blob_data_snapshot.h" -#include "storage/browser/blob/blob_storage_context.h" #include "url/gurl.h" using base::android::ConvertUTF8ToJavaString; @@ -42,49 +37,19 @@ namespace content { static void ReturnResultOnUIThread( - const base::Callback<void(const std::string&)>& callback, + base::OnceCallback<void(const std::string&)> callback, const std::string& result) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); -} - -static void RequestPlatformPathFromBlobURL( - const GURL& url, - ResourceContext* resource_context, - const base::Callback<void(const std::string&)>& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - ChromeBlobStorageContext* blob_storage_context = - GetChromeBlobStorageContextForResourceContext(resource_context); - - std::unique_ptr<storage::BlobDataHandle> handle = - blob_storage_context->context()->GetBlobDataFromPublicURL(url); - if (!handle) { - // There are plenty of cases where handle can be empty. The most trivial is - // when JS has aready revoked the given blob URL via URL.revokeObjectURL - ReturnResultOnUIThread(callback, std::string()); - return; - } - std::unique_ptr<storage::BlobDataSnapshot> data = handle->CreateSnapshot(); - if (!data) { - ReturnResultOnUIThread(callback, std::string()); - NOTREACHED(); - return; - } - const std::vector<scoped_refptr<storage::BlobDataItem>>& items = - data->items(); - - // TODO(qinmin): handle the case when the blob data is not a single file. - DLOG_IF(WARNING, items.size() != 1u) - << "More than one blob item is present: " << items.size(); - ReturnResultOnUIThread(callback, items[0]->path().value()); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(callback), result)); } static void RequestPlaformPathFromFileSystemURL( const GURL& url, int render_process_id, scoped_refptr<storage::FileSystemContext> file_system_context, - const base::Callback<void(const std::string&)>& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + media::MediaResourceGetter::GetPlatformPathCB callback) { + DCHECK(file_system_context->default_file_task_runner() + ->RunsTasksInCurrentSequence()); base::FilePath platform_path; SyncGetPlatformPath(file_system_context.get(), render_process_id, @@ -93,31 +58,34 @@ base::FilePath data_storage_path; PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path); if (data_storage_path.IsParent(platform_path)) - ReturnResultOnUIThread(callback, platform_path.value()); + ReturnResultOnUIThread(std::move(callback), platform_path.value()); else - ReturnResultOnUIThread(callback, std::string()); + ReturnResultOnUIThread(std::move(callback), std::string()); } // Posts a task to the UI thread to run the callback function. static void PostMediaMetadataCallbackTask( - const media::MediaResourceGetter::ExtractMediaMetadataCB& callback, - JNIEnv* env, ScopedJavaLocalRef<jobject>& j_metadata) { + media::MediaResourceGetter::ExtractMediaMetadataCB callback, + JNIEnv* env, + ScopedJavaLocalRef<jobject>& j_metadata) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(callback, base::TimeDelta::FromMilliseconds( - Java_MediaMetadata_getDurationInMilliseconds( - env, j_metadata)), - Java_MediaMetadata_getWidth(env, j_metadata), - Java_MediaMetadata_getHeight(env, j_metadata), - Java_MediaMetadata_isSuccess(env, j_metadata))); + base::BindOnce( + std::move(callback), + base::TimeDelta::FromMilliseconds( + Java_MediaMetadata_getDurationInMilliseconds(env, j_metadata)), + Java_MediaMetadata_getWidth(env, j_metadata), + Java_MediaMetadata_getHeight(env, j_metadata), + Java_MediaMetadata_isSuccess(env, j_metadata))); } // Gets the metadata from a media URL. When finished, a task is posted to the UI // thread to run the callback function. static void GetMediaMetadata( - const std::string& url, const std::string& cookies, + const std::string& url, + const std::string& cookies, const std::string& user_agent, - const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) { + media::MediaResourceGetter::ExtractMediaMetadataCB callback) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jstring> j_url_string = ConvertUTF8ToJavaString(env, url); @@ -127,8 +95,7 @@ ScopedJavaLocalRef<jobject> j_metadata = Java_MediaResourceGetter_extractMediaMetadata(env, j_url_string, j_cookies, j_user_agent); - - PostMediaMetadataCallbackTask(callback, env, j_metadata); + PostMediaMetadataCallbackTask(std::move(callback), env, j_metadata); } // Gets the metadata from a file descriptor. When finished, a task is posted to @@ -137,14 +104,14 @@ const int fd, const int64_t offset, const int64_t size, - const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) { + media::MediaResourceGetter::ExtractMediaMetadataCB callback) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_metadata = Java_MediaResourceGetter_extractMediaMetadataFromFd( env, fd, offset, size); - PostMediaMetadataCallbackTask(callback, env, j_metadata); + PostMediaMetadataCallbackTask(std::move(callback), env, j_metadata); } // The task object that retrieves media resources on the IO thread. @@ -161,18 +128,21 @@ net::AuthCredentials RequestAuthCredentials(const GURL& url) const; // Called by MediaResourceGetterImpl to start getting cookies for a URL. - void RequestCookies( - const GURL& url, const GURL& first_party_for_cookies, - const media::MediaResourceGetter::GetCookieCB& callback); + void RequestCookies(const GURL& url, + const GURL& first_party_for_cookies, + media::MediaResourceGetter::GetCookieCB callback); + + // Returns the task runner that all methods should be called. + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const; private: friend class base::RefCountedThreadSafe<MediaResourceGetterTask>; virtual ~MediaResourceGetterTask(); - void CheckPolicyForCookies( - const GURL& url, const GURL& first_party_for_cookies, - const media::MediaResourceGetter::GetCookieCB& callback, - const net::CookieList& cookie_list); + void CheckPolicyForCookies(const GURL& url, + const GURL& first_party_for_cookies, + media::MediaResourceGetter::GetCookieCB callback, + const net::CookieList& cookie_list); // Context getter used to get the CookieStore and auth cache. net::URLRequestContextGetter* context_getter_; @@ -202,7 +172,7 @@ net::AuthCredentials MediaResourceGetterTask::RequestAuthCredentials( const GURL& url) const { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(GetTaskRunner()->BelongsToCurrentThread()); net::HttpTransactionFactory* factory = context_getter_->GetURLRequestContext()->http_transaction_factory(); if (!factory) @@ -224,33 +194,39 @@ } void MediaResourceGetterTask::RequestCookies( - const GURL& url, const GURL& first_party_for_cookies, - const media::MediaResourceGetter::GetCookieCB& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + const GURL& url, + const GURL& first_party_for_cookies, + media::MediaResourceGetter::GetCookieCB callback) { + DCHECK(GetTaskRunner()->BelongsToCurrentThread()); ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (!policy->CanAccessDataForOrigin(render_process_id_, url)) { - callback.Run(std::string()); + std::move(callback).Run(std::string()); return; } net::CookieStore* cookie_store = context_getter_->GetURLRequestContext()->cookie_store(); if (!cookie_store) { - callback.Run(std::string()); + std::move(callback).Run(std::string()); return; } cookie_store->GetAllCookiesForURLAsync( - url, base::Bind(&MediaResourceGetterTask::CheckPolicyForCookies, this, - url, first_party_for_cookies, callback)); + url, base::BindOnce(&MediaResourceGetterTask::CheckPolicyForCookies, this, + url, first_party_for_cookies, std::move(callback))); +} + +scoped_refptr<base::SingleThreadTaskRunner> +MediaResourceGetterTask::GetTaskRunner() const { + return context_getter_->GetNetworkTaskRunner(); } void MediaResourceGetterTask::CheckPolicyForCookies( - const GURL& url, const GURL& first_party_for_cookies, - const media::MediaResourceGetter::GetCookieCB& callback, + const GURL& url, + const GURL& first_party_for_cookies, + media::MediaResourceGetter::GetCookieCB callback, const net::CookieList& cookie_list) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); if (GetContentClient()->browser()->AllowGetCookie( url, first_party_for_cookies, cookie_list, resource_context_, render_process_id_, render_frame_id_)) { @@ -258,9 +234,9 @@ context_getter_->GetURLRequestContext()->cookie_store(); net::CookieOptions options; options.set_include_httponly(); - cookie_store->GetCookiesWithOptionsAsync(url, options, callback); + cookie_store->GetCookiesWithOptionsAsync(url, options, std::move(callback)); } else { - callback.Run(std::string()); + std::move(callback).Run(std::string()); } } @@ -279,101 +255,95 @@ MediaResourceGetterImpl::~MediaResourceGetterImpl() {} void MediaResourceGetterImpl::GetAuthCredentials( - const GURL& url, const GetAuthCredentialsCB& callback) { + const GURL& url, + GetAuthCredentialsCB callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_refptr<MediaResourceGetterTask> task = new MediaResourceGetterTask( browser_context_, 0, 0); - BrowserThread::PostTaskAndReplyWithResult( - BrowserThread::IO, - FROM_HERE, - base::Bind(&MediaResourceGetterTask::RequestAuthCredentials, task, url), - base::Bind(&MediaResourceGetterImpl::GetAuthCredentialsCallback, - weak_factory_.GetWeakPtr(), callback)); + PostTaskAndReplyWithResult( + task->GetTaskRunner().get(), FROM_HERE, + base::BindOnce(&MediaResourceGetterTask::RequestAuthCredentials, task, + url), + base::BindOnce(&MediaResourceGetterImpl::GetAuthCredentialsCallback, + weak_factory_.GetWeakPtr(), std::move(callback))); } -void MediaResourceGetterImpl::GetCookies( - const GURL& url, const GURL& first_party_for_cookies, - const GetCookieCB& callback) { +void MediaResourceGetterImpl::GetCookies(const GURL& url, + const GURL& first_party_for_cookies, + GetCookieCB callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_refptr<MediaResourceGetterTask> task = new MediaResourceGetterTask( browser_context_, render_process_id_, render_frame_id_); - GetCookieCB cb = base::Bind(&MediaResourceGetterImpl::GetCookiesCallback, - weak_factory_.GetWeakPtr(), - callback); - BrowserThread::PostTask( - BrowserThread::IO, + GetCookieCB cb = + base::BindOnce(&MediaResourceGetterImpl::GetCookiesCallback, + weak_factory_.GetWeakPtr(), std::move(callback)); + task->GetTaskRunner()->PostTask( FROM_HERE, - base::Bind(&MediaResourceGetterTask::RequestCookies, - task, url, first_party_for_cookies, - base::Bind(&ReturnResultOnUIThread, cb))); + base::BindOnce(&MediaResourceGetterTask::RequestCookies, task, url, + first_party_for_cookies, + base::BindOnce(&ReturnResultOnUIThread, std::move(cb)))); } void MediaResourceGetterImpl::GetAuthCredentialsCallback( - const GetAuthCredentialsCB& callback, + GetAuthCredentialsCB callback, const net::AuthCredentials& credentials) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - callback.Run(credentials.username(), credentials.password()); + std::move(callback).Run(credentials.username(), credentials.password()); } -void MediaResourceGetterImpl::GetCookiesCallback( - const GetCookieCB& callback, const std::string& cookies) { +void MediaResourceGetterImpl::GetCookiesCallback(GetCookieCB callback, + const std::string& cookies) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - callback.Run(cookies); + std::move(callback).Run(cookies); } void MediaResourceGetterImpl::GetPlatformPathFromURL( - const GURL& url, const GetPlatformPathCB& callback) { + const GURL& url, + GetPlatformPathCB callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(url.SchemeIsFileSystem() || url.SchemeIs(url::kBlobScheme)); + DCHECK(url.SchemeIsFileSystem()); GetPlatformPathCB cb = - base::Bind(&MediaResourceGetterImpl::GetPlatformPathCallback, - weak_factory_.GetWeakPtr(), - callback); - - if (url.SchemeIs(url::kBlobScheme)) { - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&RequestPlatformPathFromBlobURL, url, - browser_context_->GetResourceContext(), cb)); - return; - } + base::BindOnce(&MediaResourceGetterImpl::GetPlatformPathCallback, + weak_factory_.GetWeakPtr(), std::move(callback)); scoped_refptr<storage::FileSystemContext> context(file_system_context_); - BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, - base::Bind(&RequestPlaformPathFromFileSystemURL, url, render_process_id_, - context, cb)); + context->default_file_task_runner()->PostTask( + FROM_HERE, base::BindOnce(&RequestPlaformPathFromFileSystemURL, url, + render_process_id_, context, std::move(cb))); } void MediaResourceGetterImpl::GetPlatformPathCallback( - const GetPlatformPathCB& callback, const std::string& platform_path) { + GetPlatformPathCB callback, + const std::string& platform_path) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - callback.Run(platform_path); + std::move(callback).Run(platform_path); } void MediaResourceGetterImpl::ExtractMediaMetadata( - const std::string& url, const std::string& cookies, - const std::string& user_agent, const ExtractMediaMetadataCB& callback) { + const std::string& url, + const std::string& cookies, + const std::string& user_agent, + ExtractMediaMetadataCB callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - base::PostTaskWithTraits( - FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&GetMediaMetadata, url, cookies, user_agent, callback)); + base::PostTaskWithTraits(FROM_HERE, + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&GetMediaMetadata, url, cookies, + user_agent, std::move(callback))); } void MediaResourceGetterImpl::ExtractMediaMetadata( const int fd, const int64_t offset, const int64_t size, - const ExtractMediaMetadataCB& callback) { + ExtractMediaMetadataCB callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - base::PostTaskWithTraits( - FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&GetMediaMetadataFromFd, fd, offset, size, callback)); + base::PostTaskWithTraits(FROM_HERE, + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&GetMediaMetadataFromFd, fd, offset, + size, std::move(callback))); } } // namespace content
diff --git a/content/browser/media/android/media_resource_getter_impl.h b/content/browser/media/android/media_resource_getter_impl.h index 268e9095..29d2c7e 100644 --- a/content/browser/media/android/media_resource_getter_impl.h +++ b/content/browser/media/android/media_resource_getter_impl.h
@@ -43,34 +43,32 @@ // media::MediaResourceGetter implementation. // Must be called on the UI thread. void GetAuthCredentials(const GURL& url, - const GetAuthCredentialsCB& callback) override; + GetAuthCredentialsCB callback) override; void GetCookies(const GURL& url, const GURL& first_party_for_cookies, - const GetCookieCB& callback) override; + GetCookieCB callback) override; void GetPlatformPathFromURL(const GURL& url, - const GetPlatformPathCB& callback) override; + GetPlatformPathCB callback) override; void ExtractMediaMetadata(const std::string& url, const std::string& cookies, const std::string& user_agent, - const ExtractMediaMetadataCB& callback) override; + ExtractMediaMetadataCB callback) override; void ExtractMediaMetadata(const int fd, const int64_t offset, const int64_t size, - const ExtractMediaMetadataCB& callback) override; + ExtractMediaMetadataCB callback) override; private: // Called when GetAuthCredentials() finishes. - void GetAuthCredentialsCallback( - const GetAuthCredentialsCB& callback, - const net::AuthCredentials& credentials); + void GetAuthCredentialsCallback(GetAuthCredentialsCB callback, + const net::AuthCredentials& credentials); // Called when GetCookies() finishes. - void GetCookiesCallback( - const GetCookieCB& callback, const std::string& cookies); + void GetCookiesCallback(GetCookieCB callback, const std::string& cookies); // Called when GetPlatformPathFromFileSystemURL() finishes. - void GetPlatformPathCallback( - const GetPlatformPathCB& callback, const std::string& platform_path); + void GetPlatformPathCallback(GetPlatformPathCB callback, + const std::string& platform_path); // BrowserContext to retrieve URLRequestContext and ResourceContext. BrowserContext* browser_context_;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 6105608..9f9fd012 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -103,10 +103,10 @@ CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) { // TODO(danakj): Don't make a FrameSinkManagerImpl when display is in the // Gpu process, instead get the mojo pointer from the Gpu process. - frame_sink_manager = + frame_sink_manager_impl = base::MakeUnique<viz::FrameSinkManagerImpl>(false, nullptr); surface_utils::ConnectWithInProcessFrameSinkManager( - &host_frame_sink_manager, frame_sink_manager.get()); + &host_frame_sink_manager, frame_sink_manager_impl.get()); } SingleThreadTaskGraphRunner task_graph_runner; @@ -117,7 +117,7 @@ // access to |in_process_frame_sink_manager_| should happen via // |host_frame_sink_manager_| instead which uses Mojo. See // http://crbug.com/657959. - std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager; + std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl; #if BUILDFLAG(ENABLE_VULKAN) scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider; @@ -419,8 +419,9 @@ } // static -cc::SurfaceManager* CompositorImpl::GetSurfaceManager() { - return g_compositor_dependencies.Get().frame_sink_manager->surface_manager(); +cc::FrameSinkManager* CompositorImpl::GetFrameSinkManager() { + return g_compositor_dependencies.Get() + .frame_sink_manager_impl->frame_sink_manager(); } // static @@ -452,7 +453,7 @@ num_successive_context_creation_failures_(0), layer_tree_frame_sink_request_pending_(false), weak_factory_(this) { - GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_); + GetFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_); DCHECK(client); DCHECK(root_window); DCHECK(root_window->GetLayer() == nullptr); @@ -470,7 +471,7 @@ root_window_->SetLayer(nullptr); // Clean-up any surface references. SetSurface(NULL); - GetSurfaceManager()->InvalidateFrameSinkId(frame_sink_id_); + GetFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_); } bool CompositorImpl::IsForSubframe() { @@ -580,7 +581,7 @@ has_layer_tree_frame_sink_ = false; pending_frames_ = 0; if (display_) { - GetSurfaceManager()->UnregisterBeginFrameSource( + GetFrameSinkManager()->UnregisterBeginFrameSource( root_window_->GetBeginFrameSource()); } display_.reset(); @@ -794,7 +795,7 @@ // TODO(danakj): Populate gpu_capabilities_ for VulkanContextProvider. } - cc::SurfaceManager* manager = GetSurfaceManager(); + cc::FrameSinkManager* manager = GetFrameSinkManager(); auto* task_runner = base::ThreadTaskRunnerHandle::Get().get(); std::unique_ptr<cc::DisplayScheduler> scheduler(new cc::DisplayScheduler( root_window_->GetBeginFrameSource(), task_runner, @@ -828,7 +829,7 @@ ->GetDisplayNearestWindow(root_window_) .color_space(); display_->SetColorSpace(display_color_space, display_color_space); - GetSurfaceManager()->RegisterBeginFrameSource( + GetFrameSinkManager()->RegisterBeginFrameSource( root_window_->GetBeginFrameSource(), frame_sink_id_); host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); } @@ -898,8 +899,8 @@ void CompositorImpl::AddChildFrameSink(const cc::FrameSinkId& frame_sink_id) { if (has_layer_tree_frame_sink_) { - GetSurfaceManager()->RegisterFrameSinkHierarchy(frame_sink_id_, - frame_sink_id); + GetFrameSinkManager()->RegisterFrameSinkHierarchy(frame_sink_id_, + frame_sink_id); } else { pending_child_frame_sink_ids_.insert(frame_sink_id); } @@ -912,8 +913,8 @@ pending_child_frame_sink_ids_.erase(it); return; } - GetSurfaceManager()->UnregisterFrameSinkHierarchy(frame_sink_id_, - frame_sink_id); + GetFrameSinkManager()->UnregisterFrameSinkHierarchy(frame_sink_id_, + frame_sink_id); } bool CompositorImpl::HavePendingReadbacks() {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index b7db712..3279a62 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -35,10 +35,10 @@ class AnimationHost; class Display; class FrameSinkId; +class FrameSinkManager; class Layer; class LayerTreeHost; class OutputSurface; -class SurfaceManager; class VulkanContextProvider; } @@ -64,7 +64,7 @@ static bool IsInitialized(); - static cc::SurfaceManager* GetSurfaceManager(); + static cc::FrameSinkManager* GetFrameSinkManager(); static viz::HostFrameSinkManager* GetHostFrameSinkManager(); static cc::FrameSinkId AllocateFrameSinkId();
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 383015a..95e7c87 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -19,9 +19,9 @@ #include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "cc/surfaces/compositor_frame_sink_support.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_hittest.h" -#include "cc/surfaces/surface_manager.h" #include "components/viz/common/gl_helper.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/gpu/compositor_util.h" @@ -53,8 +53,9 @@ frame_evictor_(new viz::FrameEvictor(this)) { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); factory->GetContextFactory()->AddObserver(this); - factory->GetContextFactoryPrivate()->GetSurfaceManager()->RegisterFrameSinkId( - frame_sink_id_); + factory->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->RegisterFrameSinkId(frame_sink_id_); CreateCompositorFrameSinkSupport(); } @@ -176,7 +177,8 @@ cc::SurfaceId surface_id(frame_sink_id_, local_surface_id_); if (!surface_id.is_valid()) return surface_id; - cc::SurfaceHittest hittest(delegate, GetSurfaceManager()); + cc::SurfaceHittest hittest(delegate, + GetFrameSinkManager()->surface_manager()); gfx::Transform target_transform; cc::SurfaceId target_local_surface_id = hittest.GetTargetSurfaceAtPoint(surface_id, point, &target_transform); @@ -197,7 +199,7 @@ if (original_surface == surface_id) return true; - cc::SurfaceHittest hittest(nullptr, GetSurfaceManager()); + cc::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager()); return hittest.TransformPointToTargetSurface(original_surface, surface_id, transformed_point); } @@ -448,8 +450,8 @@ EvictDelegatedFrame(); } else { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - cc::SurfaceManager* manager = - factory->GetContextFactoryPrivate()->GetSurfaceManager(); + cc::FrameSinkManager* manager = + factory->GetContextFactoryPrivate()->GetFrameSinkManager(); frame.metadata.latency_info.insert(frame.metadata.latency_info.end(), skipped_latency_info_list_.begin(), @@ -466,7 +468,7 @@ cc::SurfaceInfo surface_info(surface_id, frame_device_scale_factor, frame_size); client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface( - surface_info, manager->reference_factory()); + surface_info, manager->surface_manager()->reference_factory()); client_->DelegatedFrameHostGetLayer()->SetFallbackSurface(surface_info); current_surface_size_ = frame_size; current_scale_factor_ = frame_device_scale_factor; @@ -776,7 +778,7 @@ ResetCompositorFrameSinkSupport(); factory->GetContextFactoryPrivate() - ->GetSurfaceManager() + ->GetFrameSinkManager() ->InvalidateFrameSinkId(frame_sink_id_); DCHECK(!vsync_manager_.get()); @@ -842,7 +844,7 @@ constexpr bool needs_sync_points = true; ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); support_ = cc::CompositorFrameSinkSupport::Create( - this, factory->GetContextFactoryPrivate()->GetSurfaceManager(), + this, factory->GetContextFactoryPrivate()->GetFrameSinkManager(), frame_sink_id_, is_root, handles_frame_sink_id_invalidation, needs_sync_points); if (compositor_)
diff --git a/content/browser/renderer_host/input/input_device_change_observer.cc b/content/browser/renderer_host/input/input_device_change_observer.cc index e0b66d9..704b40c 100644 --- a/content/browser/renderer_host/input/input_device_change_observer.cc +++ b/content/browser/renderer_host/input/input_device_change_observer.cc
@@ -4,12 +4,15 @@ #include "content/browser/renderer_host/input/input_device_change_observer.h" #include "base/trace_event/trace_event.h" +#include "build/build_config.h" #include "content/public/common/web_preferences.h" #if defined(OS_WIN) #include "ui/events/devices/input_device_observer_win.h" #elif defined(OS_LINUX) #include "ui/events/devices/input_device_manager.h" +#elif defined(OS_ANDROID) +#include "ui/events/devices/input_device_observer_android.h" #endif namespace content { @@ -20,6 +23,8 @@ ui::InputDeviceObserverWin::GetInstance()->AddObserver(this); #elif defined(OS_LINUX) ui::InputDeviceManager::GetInstance()->AddObserver(this); +#elif defined(OS_ANDROID) + ui::InputDeviceObserverAndroid::GetInstance()->AddObserver(this); #endif } @@ -28,6 +33,8 @@ ui::InputDeviceObserverWin::GetInstance()->RemoveObserver(this); #elif defined(OS_LINUX) ui::InputDeviceManager::GetInstance()->RemoveObserver(this); +#elif defined(OS_ANDROID) + ui::InputDeviceObserverAndroid::GetInstance()->RemoveObserver(this); #endif render_view_host_ = nullptr; }
diff --git a/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc b/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc index 013f8c4..6125b87 100644 --- a/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc +++ b/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc
@@ -4,6 +4,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" @@ -25,7 +26,7 @@ } // namespace -#if defined(OS_WIN) || defined(OS_LINUX) +#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID) IN_PROC_BROWSER_TEST_F(InteractionMediaQueriesDynamicTest, PointerMediaQueriesDynamic) { GURL test_url = GetTestUrl("", "interaction-mq-dynamic.html");
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc index fa69e4ad..12f039c 100644 --- a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc +++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
@@ -98,7 +98,7 @@ } void LegacyIPCWidgetInputHandler::DispatchEvent( - content::mojom::EventPtr event, + std::unique_ptr<content::InputEvent> event, DispatchEventCallback callback) { // We only expect these events to be called with the mojo enabled input // channel. The LegacyInputRouterImpl will handle sending the events @@ -107,7 +107,7 @@ } void LegacyIPCWidgetInputHandler::DispatchNonBlockingEvent( - content::mojom::EventPtr) { + std::unique_ptr<content::InputEvent> event) { // We only expect these events to be called with the mojo enabled input // channel. The LegacyInputRouterImpl will handle sending the events // directly.
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h index af0ee2d..9bc8f0c6 100644 --- a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h +++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
@@ -41,9 +41,10 @@ void RequestTextInputStateUpdate() override; void RequestCompositionUpdates(bool immediate_request, bool monitor_request) override; - void DispatchEvent(content::mojom::EventPtr event, + void DispatchEvent(std::unique_ptr<content::InputEvent> event, DispatchEventCallback callback) override; - void DispatchNonBlockingEvent(content::mojom::EventPtr) override; + void DispatchNonBlockingEvent( + std::unique_ptr<content::InputEvent> event) override; private: void SendInput(std::unique_ptr<IPC::Message> message);
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc index 745e0b1..7cb16fd1 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "cc/surfaces/surface_manager.h" +#include "cc/surfaces/frame_sink_manager.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" @@ -70,11 +70,12 @@ void OffscreenCanvasSurfaceImpl::Require(const cc::SurfaceId& surface_id, const cc::SurfaceSequence& sequence) { - GetSurfaceManager()->RequireSequence(surface_id, sequence); + GetFrameSinkManager()->surface_manager()->RequireSequence(surface_id, + sequence); } void OffscreenCanvasSurfaceImpl::Satisfy(const cc::SurfaceSequence& sequence) { - GetSurfaceManager()->SatisfySequence(sequence); + GetFrameSinkManager()->surface_manager()->SatisfySequence(sequence); } void OffscreenCanvasSurfaceImpl::OnSurfaceConnectionClosed() {
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 5f4a396a..43b7512a120 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc
@@ -201,17 +201,21 @@ void RenderMessageFilter::CreateNewWidget(int32_t opener_id, blink::WebPopupType popup_type, + mojom::WidgetPtr widget, CreateNewWidgetCallback callback) { int route_id = MSG_ROUTING_NONE; - render_widget_helper_->CreateNewWidget(opener_id, popup_type, &route_id); + render_widget_helper_->CreateNewWidget(opener_id, popup_type, + std::move(widget), &route_id); std::move(callback).Run(route_id); } void RenderMessageFilter::CreateFullscreenWidget( int opener_id, + mojom::WidgetPtr widget, CreateFullscreenWidgetCallback callback) { int route_id = 0; - render_widget_helper_->CreateNewFullscreenWidget(opener_id, &route_id); + render_widget_helper_->CreateNewFullscreenWidget(opener_id, std::move(widget), + &route_id); std::move(callback).Run(route_id); }
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 5cdea21..68b59b1 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h
@@ -113,8 +113,10 @@ void GenerateRoutingID(GenerateRoutingIDCallback routing_id) override; void CreateNewWidget(int32_t opener_id, blink::WebPopupType popup_type, + mojom::WidgetPtr widget, CreateNewWidgetCallback callback) override; void CreateFullscreenWidget(int opener_id, + mojom::WidgetPtr widget, CreateFullscreenWidgetCallback callback) override; void GetSharedBitmapAllocationNotifier( cc::mojom::SharedBitmapAllocationNotifierAssociatedRequest request)
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index a0791373..caea5b7 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2898,6 +2898,10 @@ void RenderProcessHostImpl::SetEchoCanceller3(bool enable) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + // TODO(hlundin) Implement a test to verify that the setting works both with + // aec_dump_consumers already registered, and with those registered in the + // future. crbug.com/740104 + override_aec3_ = enable; // Piggybacking on AEC dumps. // TODO(hlundin): Change name for aec_dump_consumers_; @@ -3730,6 +3734,9 @@ WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath()); EnableAecDumpForId(file_with_extensions, id); } + if (override_aec3_) { + Send(new AudioProcessingMsg_EnableAec3(id, *override_aec3_)); + } } void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 94a0d1f7..9889ce7 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -650,6 +650,7 @@ // Must be accessed on UI thread. std::vector<int> aec_dump_consumers_; + base::Optional<bool> override_aec3_; WebRtcStopRtpDumpCallback stop_rtp_dump_callback_;
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index 1490ac4..1740108 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -14,6 +14,7 @@ #include "base/strings/string16.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/common/content_export.h" +#include "content/common/render_message_filter.mojom.h" #include "net/base/load_states.h" #include "third_party/WebKit/public/web/WebPopupType.h" @@ -130,11 +131,13 @@ // is (select, autofill...). virtual void CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) {} // Creates a full screen RenderWidget. Similar to above. virtual void CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) {} + int32_t route_id, + mojom::WidgetPtr widget) {} // Show the newly created widget with the specified bounds. // The widget is identified by the route_id passed to CreateNewWidget.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 006dab2..1b14ec9 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -756,12 +756,16 @@ } void RenderViewHostImpl::CreateNewWidget(int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) { - delegate_->CreateNewWidget(GetProcess()->GetID(), route_id, popup_type); + delegate_->CreateNewWidget(GetProcess()->GetID(), route_id, std::move(widget), + popup_type); } -void RenderViewHostImpl::CreateNewFullscreenWidget(int32_t route_id) { - delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id); +void RenderViewHostImpl::CreateNewFullscreenWidget(int32_t route_id, + mojom::WidgetPtr widget) { + delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id, + std::move(widget)); } void RenderViewHostImpl::OnShowWidget(int route_id,
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index c36ebdd..7e0cc57 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -24,6 +24,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_owner_delegate.h" #include "content/browser/site_instance_impl.h" +#include "content/common/render_message_filter.mojom.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/render_view_host.h" @@ -177,10 +178,12 @@ // Creates a new RenderWidget with the given route id. |popup_type| indicates // if this widget is a popup and what kind of popup it is (select, autofill). - void CreateNewWidget(int32_t route_id, blink::WebPopupType popup_type); + void CreateNewWidget(int32_t route_id, + mojom::WidgetPtr widget, + blink::WebPopupType popup_type); // Creates a full screen RenderWidget. - void CreateNewFullscreenWidget(int32_t route_id); + void CreateNewFullscreenWidget(int32_t route_id, mojom::WidgetPtr widget); // Send RenderViewReady to observers once the process is launched, but not // re-entrantly.
diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc index b2f5bd5..28d28aa 100644 --- a/content/browser/renderer_host/render_view_host_unittest.cc +++ b/content/browser/renderer_host/render_view_host_unittest.cc
@@ -31,6 +31,15 @@ namespace content { +class WidgetImpl : public mojom::Widget { + public: + explicit WidgetImpl(mojo::InterfaceRequest<mojom::Widget> request) + : binding_(this, std::move(request)) {} + + private: + mojo::Binding<mojom::Widget> binding_; +}; + class RenderViewHostTestBrowserClient : public TestContentBrowserClient { public: RenderViewHostTestBrowserClient() {} @@ -79,7 +88,11 @@ // Create a full screen popup RenderWidgetHost and View. TEST_F(RenderViewHostTest, CreateFullscreenWidget) { int32_t routing_id = process()->GetNextRoutingID(); - test_rvh()->CreateNewFullscreenWidget(routing_id); + + mojom::WidgetPtr widget; + std::unique_ptr<WidgetImpl> widget_impl = + base::MakeUnique<WidgetImpl>(mojo::MakeRequest(&widget)); + test_rvh()->CreateNewFullscreenWidget(routing_id, std::move(widget)); } // Ensure we do not grant bindings to a process shared with unprivileged views.
diff --git a/content/browser/renderer_host/render_widget_helper.cc b/content/browser/renderer_host/render_widget_helper.cc index 22c246a..9c1be29 100644 --- a/content/browser/renderer_host/render_widget_helper.cc +++ b/content/browser/renderer_host/render_widget_helper.cc
@@ -87,37 +87,48 @@ void RenderWidgetHelper::CreateNewWidget(int opener_id, blink::WebPopupType popup_type, + mojom::WidgetPtr widget, int* route_id) { *route_id = GetNextRoutingID(); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&RenderWidgetHelper::OnCreateWidgetOnUI, - this, opener_id, *route_id, popup_type)); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&RenderWidgetHelper::OnCreateWidgetOnUI, this, opener_id, + *route_id, widget.PassInterface(), popup_type)); } void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id, + mojom::WidgetPtr widget, int* route_id) { *route_id = GetNextRoutingID(); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&RenderWidgetHelper::OnCreateFullscreenWidgetOnUI, this, - opener_id, *route_id)); + base::BindOnce(&RenderWidgetHelper::OnCreateFullscreenWidgetOnUI, this, + opener_id, *route_id, widget.PassInterface())); } void RenderWidgetHelper::OnCreateWidgetOnUI(int32_t opener_id, int32_t route_id, + mojom::WidgetPtrInfo widget_info, blink::WebPopupType popup_type) { + mojom::WidgetPtr widget; + widget.Bind(std::move(widget_info)); RenderViewHostImpl* host = RenderViewHostImpl::FromID( render_process_id_, opener_id); if (host) - host->CreateNewWidget(route_id, popup_type); + host->CreateNewWidget(route_id, std::move(widget), popup_type); } -void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(int32_t opener_id, - int32_t route_id) { +void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI( + int32_t opener_id, + int32_t route_id, + mojom::WidgetPtrInfo widget_info) { + mojom::WidgetPtr widget; + widget.Bind(std::move(widget_info)); RenderViewHostImpl* host = RenderViewHostImpl::FromID( render_process_id_, opener_id); if (host) - host->CreateNewFullscreenWidget(route_id); + host->CreateNewFullscreenWidget(route_id, std::move(widget)); } } // namespace content
diff --git a/content/browser/renderer_host/render_widget_helper.h b/content/browser/renderer_host/render_widget_helper.h index ffd67fe..a6e185c1 100644 --- a/content/browser/renderer_host/render_widget_helper.h +++ b/content/browser/renderer_host/render_widget_helper.h
@@ -58,8 +58,11 @@ // IO THREAD ONLY ----------------------------------------------------------- void CreateNewWidget(int opener_id, blink::WebPopupType popup_type, + mojom::WidgetPtr, int* route_id); - void CreateNewFullscreenWidget(int opener_id, int* route_id); + void CreateNewFullscreenWidget(int opener_id, + mojom::WidgetPtr, + int* route_id); private: friend class base::RefCountedThreadSafe<RenderWidgetHelper>; @@ -71,10 +74,13 @@ // Called on the UI thread to finish creating a widget. void OnCreateWidgetOnUI(int32_t opener_id, int32_t route_id, + mojom::WidgetPtrInfo widget, blink::WebPopupType popup_type); // Called on the UI thread to create a fullscreen widget. - void OnCreateFullscreenWidgetOnUI(int32_t opener_id, int32_t route_id); + void OnCreateFullscreenWidgetOnUI(int32_t opener_id, + int32_t route_id, + mojom::WidgetPtrInfo widget); // Called on the IO thread to resume a paused navigation in the network // stack without transferring it to a new renderer process.
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index d4b5e98..845d0f8d 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -30,9 +30,9 @@ #include "cc/output/copy_output_result.h" #include "cc/output/latency_info_swap_promise.h" #include "cc/resources/single_release_callback.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_hittest.h" -#include "cc/surfaces/surface_manager.h" #include "cc/trees/layer_tree_host.h" #include "components/viz/common/gl_helper.h" #include "content/browser/accessibility/browser_accessibility_manager_android.h" @@ -480,7 +480,7 @@ cc::FrameSinkId frame_sink_id = host_->AllocateFrameSinkId(false /* is_guest_view_hack */); delegated_frame_host_.reset(new ui::DelegatedFrameHostAndroid( - &view_, CompositorImpl::GetSurfaceManager(), this, frame_sink_id)); + &view_, CompositorImpl::GetFrameSinkManager(), this, frame_sink_id)); // Let the page-level input event router know about our frame sink ID // for surface-based hit testing. @@ -842,7 +842,8 @@ cc::SurfaceId surface_id = delegated_frame_host_->SurfaceId(); if (surface_id.is_valid()) { - cc::SurfaceHittest hittest(delegate, GetSurfaceManager()); + cc::SurfaceHittest hittest(delegate, + GetFrameSinkManager()->surface_manager()); gfx::Transform target_transform; surface_id = hittest.GetTargetSurfaceAtPoint(surface_id, point_in_pixels, &target_transform); @@ -905,7 +906,7 @@ return true; *transformed_point = point_in_pixels; - cc::SurfaceHittest hittest(nullptr, GetSurfaceManager()); + cc::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager()); if (!hittest.TransformPointToTargetSurface(original_surface, surface_id, transformed_point)) return false;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 2e142be..489533b 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -27,9 +27,9 @@ #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_metadata.h" #include "cc/output/copy_output_request.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface.h" -#include "cc/surfaces/surface_manager.h" #include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_external_begin_frame_source.h" #include "cc/test/fake_surface_observer.h" @@ -2447,8 +2447,9 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) { cc::FakeSurfaceObserver manager_observer; ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - cc::SurfaceManager* manager = - factory->GetContextFactoryPrivate()->GetSurfaceManager(); + cc::SurfaceManager* manager = factory->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->surface_manager(); manager->AddObserver(&manager_observer); gfx::Size view_size(100, 100); @@ -2600,8 +2601,9 @@ cc::SurfaceId id = view_->GetDelegatedFrameHost()->SurfaceIdForTesting(); if (id.is_valid()) { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - cc::SurfaceManager* manager = - factory->GetContextFactoryPrivate()->GetSurfaceManager(); + cc::SurfaceManager* manager = factory->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->surface_manager(); cc::Surface* surface = manager->GetSurfaceForId(id); EXPECT_TRUE(surface); @@ -3446,8 +3448,9 @@ cc::FakeSurfaceObserver observer; ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - cc::SurfaceManager* surface_manager = - factory->GetContextFactoryPrivate()->GetSurfaceManager(); + cc::SurfaceManager* surface_manager = factory->GetContextFactoryPrivate() + ->GetFrameSinkManager() + ->surface_manager(); surface_manager->AddObserver(&observer); view_->SetNeedsBeginFrames(true);
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 28b9a02..35c121a 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -173,6 +173,14 @@ } // namespace +class WidgetImpl : public mojom::Widget { + public: + explicit WidgetImpl(mojo::InterfaceRequest<mojom::Widget> request) + : binding_(this, std::move(request)) {} + + private: + mojo::Binding<mojom::Widget> binding_; +}; // The goal of these tests will be to "simulate" exploited renderer processes, // which can send arbitrary IPC messages and confuse browser process internal @@ -294,11 +302,16 @@ PrepareToDuplicateHosts(shell(), &duplicate_routing_id); EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id); + mojom::WidgetPtr widget; + std::unique_ptr<WidgetImpl> widget_impl = + base::MakeUnique<WidgetImpl>(mojo::MakeRequest(&widget)); + // Since this test executes on the UI thread and hopping threads might cause // different timing in the test, let's simulate a CreateNewWidget call coming // from the IO thread. Use the existing window routing id to cause a // deliberate collision. - pending_rvh->CreateNewWidget(duplicate_routing_id, blink::kWebPopupTypePage); + pending_rvh->CreateNewWidget(duplicate_routing_id, std::move(widget), + blink::kWebPopupTypePage); // If the above operation doesn't crash, the test has succeeded! }
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc index 84ea2af..52df13b 100644 --- a/content/browser/web_contents/web_contents_android.cc +++ b/content/browser/web_contents/web_contents_android.cc
@@ -317,12 +317,6 @@ return rwhva->GetCachedBackgroundColor(); } -ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL( - JNIEnv* env, - const JavaParamRef<jobject>& obj) const { - return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec()); -} - ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL( JNIEnv* env, const JavaParamRef<jobject>&) const {
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h index 6d26a839..f18a3b8 100644 --- a/content/browser/web_contents/web_contents_android.h +++ b/content/browser/web_contents/web_contents_android.h
@@ -74,9 +74,6 @@ const base::android::JavaParamRef<jobject>& obj); jint GetBackgroundColor(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - base::android::ScopedJavaLocalRef<jstring> GetURL( - JNIEnv* env, - const base::android::JavaParamRef<jobject>&) const; base::android::ScopedJavaLocalRef<jstring> GetLastCommittedURL( JNIEnv* env, const base::android::JavaParamRef<jobject>&) const;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9738d39b..cb077e5bd 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2357,18 +2357,23 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) { - CreateNewWidget(render_process_id, route_id, false, popup_type); + CreateNewWidget(render_process_id, route_id, false, std::move(widget), + popup_type); } void WebContentsImpl::CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) { - CreateNewWidget(render_process_id, route_id, true, blink::kWebPopupTypeNone); + int32_t route_id, + mojom::WidgetPtr widget) { + CreateNewWidget(render_process_id, route_id, true, std::move(widget), + blink::kWebPopupTypeNone); } void WebContentsImpl::CreateNewWidget(int32_t render_process_id, int32_t route_id, bool is_fullscreen, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) { RenderProcessHost* process = RenderProcessHost::FromID(render_process_id); // A message to create a new widget can only come from an active process for @@ -3157,6 +3162,12 @@ return interstitial_page_ != nullptr; } +void WebContentsImpl::AdjustPreviewsStateForNavigation( + PreviewsState* previews_state) { + if (delegate_) + delegate_->AdjustPreviewsStateForNavigation(previews_state); +} + InterstitialPage* WebContentsImpl::GetInterstitialPage() const { return interstitial_page_; }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 785da1a..d897b52 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -403,6 +403,7 @@ void RestoreFocus() override; void FocusThroughTabTraversal(bool reverse) override; bool ShowingInterstitialPage() const override; + void AdjustPreviewsStateForNavigation(PreviewsState* previews_state) override; InterstitialPage* GetInterstitialPage() const override; bool IsSavable() override; void OnSavePage() override; @@ -599,9 +600,11 @@ void UpdatePreferredSize(const gfx::Size& pref_size) override; void CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) override; void CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) override; + int32_t route_id, + mojom::WidgetPtr widget) override; void ShowCreatedWidget(int process_id, int route_id, const gfx::Rect& initial_rect) override; @@ -1191,6 +1194,7 @@ void CreateNewWidget(int32_t render_process_id, int32_t route_id, bool is_fullscreen, + mojom::WidgetPtr widget, blink::WebPopupType popup_type); // Helper for ShowCreatedWidget/ShowCreatedFullscreenWidget.
diff --git a/content/browser/webrtc/webrtc_media_recorder_browsertest.cc b/content/browser/webrtc/webrtc_media_recorder_browsertest.cc index 2a51201..3d815a27 100644 --- a/content/browser/webrtc/webrtc_media_recorder_browsertest.cc +++ b/content/browser/webrtc/webrtc_media_recorder_browsertest.cc
@@ -73,13 +73,7 @@ MakeTypicalCall("testStartStopAndRecorderState();", kMediaRecorderHtmlFile); } -// Flaky on Linux Tsan (crbug.com/736268) -#if defined(THREAD_SANITIZER) -#define MAYBE_StartAndDataAvailable DISABLED_StartAndDataAvailable -#else -#define MAYBE_StartAndDataAvailable StartAndDataAvailable -#endif -IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, MAYBE_StartAndDataAvailable) { +IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, StartAndDataAvailable) { MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator); MakeTypicalCall(base::StringPrintf("testStartAndDataAvailable(\"%s\");", GetParam().mime_type.c_str()), @@ -150,41 +144,18 @@ kMediaRecorderHtmlFile); } -// Flaky on Linux Tsan (crbug.com/736268) -#if defined(THREAD_SANITIZER) -#define MAYBE_IllegalStopThrowsDOMError DISABLED_IllegalStopThrowsDOMError -#else -#define MAYBE_IllegalStopThrowsDOMError IllegalStopThrowsDOMError -#endif -IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, - MAYBE_IllegalStopThrowsDOMError) { +IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, IllegalStopThrowsDOMError) { MakeTypicalCall("testIllegalStopThrowsDOMError();", kMediaRecorderHtmlFile); } -// Flaky on Linux Tsan (crbug.com/736268) -#if defined(THREAD_SANITIZER) -#define MAYBE_IllegalStartWhileRecordingThrowsDOMError \ - DISABLED_IllegalStartWhileRecordingThrowsDOMError -#else -#define MAYBE_IllegalStartWhileRecordingThrowsDOMError \ - IllegalStartWhileRecordingThrowsDOMError -#endif IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, - MAYBE_IllegalStartWhileRecordingThrowsDOMError) { + IllegalStartWhileRecordingThrowsDOMError) { MakeTypicalCall("testIllegalStartInRecordingStateThrowsDOMError();", kMediaRecorderHtmlFile); } -// Flaky on Linux Tsan (crbug.com/736268) -#if defined(THREAD_SANITIZER) -#define MAYBE_IllegalStartWhilePausedThrowsDOMError \ - DISABLED_IllegalStartWhilePausedThrowsDOMError -#else -#define MAYBE_IllegalStartWhilePausedThrowsDOMError \ - IllegalStartWhilePausedThrowsDOMError -#endif IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, - MAYBE_IllegalStartWhilePausedThrowsDOMError) { + IllegalStartWhilePausedThrowsDOMError) { MakeTypicalCall("testIllegalStartInPausedStateThrowsDOMError();", kMediaRecorderHtmlFile); }
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index f871bb4..0cc4552 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -176,6 +176,8 @@ "input/input_event_dispatch_type.h", "input/input_event_stream_validator.cc", "input/input_event_stream_validator.h", + "input/input_event_struct_traits.cc", + "input/input_event_struct_traits.h", "input/input_param_traits.cc", "input/input_param_traits.h", "input/synthetic_gesture_packet.cc", @@ -283,8 +285,6 @@ "sandbox_init_mac.cc", "sandbox_init_mac.h", "sandbox_init_win.cc", - "sandbox_linux/android/sandbox_bpf_base_policy_android.cc", - "sandbox_linux/android/sandbox_bpf_base_policy_android.h", "sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc", "sandbox_linux/bpf_cros_arm_gpu_policy_linux.h", "sandbox_linux/bpf_gpu_policy_linux.cc", @@ -540,12 +540,6 @@ "sandbox_linux/sandbox_bpf_base_policy_linux.h", ] } - if (is_android) { - sources -= [ - "sandbox_linux/android/sandbox_bpf_base_policy_android.cc", - "sandbox_linux/android/sandbox_bpf_base_policy_android.h", - ] - } } if (is_mac) { @@ -626,6 +620,7 @@ "service_worker/service_worker_types.mojom", "storage_partition_service.mojom", "video_capture.mojom", + "widget.mojom", "worker_url_loader_factory_provider.mojom", ]
diff --git a/content/common/input/OWNERS b/content/common/input/OWNERS index d74c0a7..ec220b4 100644 --- a/content/common/input/OWNERS +++ b/content/common/input/OWNERS
@@ -6,6 +6,8 @@ per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS # TEAM: input-dev@chromium.org # COMPONENT: Blink>Input
diff --git a/content/common/input/input_event_struct_traits.cc b/content/common/input/input_event_struct_traits.cc new file mode 100644 index 0000000..a02c660 --- /dev/null +++ b/content/common/input/input_event_struct_traits.cc
@@ -0,0 +1,543 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/input/input_event_struct_traits.h" + +#include "base/i18n/char_iterator.h" +#include "content/common/input_messages.h" +#include "third_party/WebKit/public/platform/WebKeyboardEvent.h" +#include "ui/latency/mojo/latency_info_struct_traits.h" + +namespace mojo { +namespace { + +void CopyString(blink::WebUChar* dst, const base::string16& text) { + base::i18n::UTF16CharIterator iter(&text); + size_t pos = 0; + while (!iter.end() && pos < blink::WebKeyboardEvent::kTextLengthCap - 1) { + dst[pos++] = iter.get(); + iter.Advance(); + } + dst[pos] = '\0'; +} + +content::mojom::PointerDataPtr PointerDataFromPointerProperties( + const blink::WebPointerProperties& pointer, + content::mojom::MouseDataPtr mouse_data) { + return content::mojom::PointerData::New( + pointer.id, pointer.force, pointer.tilt_x, pointer.tilt_y, + pointer.tangential_pressure, pointer.twist, pointer.button, + pointer.pointer_type, pointer.movement_x, pointer.movement_y, + pointer.PositionInWidget(), pointer.PositionInScreen(), + std::move(mouse_data)); +} + +void PointerPropertiesFromPointerData( + const content::mojom::PointerDataPtr& pointer_data, + blink::WebPointerProperties* pointer_properties) { + pointer_properties->id = pointer_data->pointer_id; + pointer_properties->force = pointer_data->force; + pointer_properties->tilt_x = pointer_data->tilt_x; + pointer_properties->tilt_y = pointer_data->tilt_y; + pointer_properties->tangential_pressure = pointer_data->tangential_pressure; + pointer_properties->twist = pointer_data->twist; + pointer_properties->button = pointer_data->button; + pointer_properties->pointer_type = pointer_data->pointer_type; + pointer_properties->movement_x = pointer_data->movement_x; + pointer_properties->movement_y = pointer_data->movement_y; +} + +void TouchPointPropertiesFromPointerData( + const content::mojom::TouchPointPtr& mojo_touch_point, + blink::WebTouchPoint* touch_point) { + PointerPropertiesFromPointerData(mojo_touch_point->pointer_data, touch_point); + touch_point->state = mojo_touch_point->state; + touch_point->radius_x = mojo_touch_point->radius_x; + touch_point->radius_y = mojo_touch_point->radius_y; + touch_point->rotation_angle = mojo_touch_point->rotation_angle; + touch_point->SetPositionInWidget( + mojo_touch_point->pointer_data->widget_position.x(), + mojo_touch_point->pointer_data->widget_position.y()); + touch_point->SetPositionInScreen( + mojo_touch_point->pointer_data->screen_position.x(), + mojo_touch_point->pointer_data->screen_position.y()); +} + +// TODO(dtapuska): Remove once SetPositionInXXX moves to WebPointerProperties. +void MouseEventPropertiesFromPointerData( + const content::mojom::PointerDataPtr& pointer_data, + blink::WebMouseEvent* mouse_event) { + PointerPropertiesFromPointerData(pointer_data, mouse_event); + mouse_event->SetPositionInWidget(pointer_data->widget_position.x(), + pointer_data->widget_position.y()); + mouse_event->SetPositionInScreen(pointer_data->screen_position.x(), + pointer_data->screen_position.y()); +} + +} // namespace + +bool StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::Read( + content::mojom::EventDataView event, + InputEventUniquePtr* out) { + DCHECK(!out->get()); + + out->reset(new content::InputEvent()); + + blink::WebInputEvent::Type type; + if (!event.ReadType(&type)) + return false; + + if (blink::WebInputEvent::IsKeyboardEventType(type)) { + content::mojom::KeyDataPtr key_data; + if (!event.ReadKeyData<content::mojom::KeyDataPtr>(&key_data)) + return false; + + (*out)->web_event.reset(new blink::WebKeyboardEvent( + type, event.modifiers(), event.timestamp_seconds())); + + blink::WebKeyboardEvent* key_event = + static_cast<blink::WebKeyboardEvent*>((*out)->web_event.get()); + key_event->windows_key_code = key_data->windows_key_code; + key_event->native_key_code = key_data->native_key_code; + key_event->dom_code = key_data->dom_code; + key_event->dom_key = key_data->dom_key; + key_event->is_system_key = key_data->is_system_key; + key_event->is_browser_shortcut = key_data->is_browser_shortcut; + CopyString(key_event->text, key_data->text); + CopyString(key_event->unmodified_text, key_data->unmodified_text); + } else if (blink::WebInputEvent::IsGestureEventType(type)) { + content::mojom::GestureDataPtr gesture_data; + if (!event.ReadGestureData<content::mojom::GestureDataPtr>(&gesture_data)) + return false; + (*out)->web_event.reset(new blink::WebGestureEvent( + type, event.modifiers(), event.timestamp_seconds())); + + blink::WebGestureEvent* gesture_event = + static_cast<blink::WebGestureEvent*>((*out)->web_event.get()); + gesture_event->x = gesture_data->widget_position.x(); + gesture_event->y = gesture_data->widget_position.y(); + gesture_event->global_x = gesture_data->screen_position.x(); + gesture_event->global_y = gesture_data->screen_position.y(); + gesture_event->source_device = gesture_data->source_device; + gesture_event->unique_touch_event_id = gesture_data->unique_touch_event_id; + gesture_event->resending_plugin_id = gesture_data->resending_plugin_id; + + if (gesture_data->contact_size) { + switch (type) { + default: + break; + case blink::WebInputEvent::Type::kGestureTapDown: + case blink::WebInputEvent::Type::kGestureTapUnconfirmed: + case blink::WebInputEvent::Type::kGestureDoubleTap: + gesture_event->data.tap_down.width = + gesture_data->contact_size->width(); + gesture_event->data.tap_down.height = + gesture_data->contact_size->height(); + break; + case blink::WebInputEvent::Type::kGestureShowPress: + gesture_event->data.show_press.width = + gesture_data->contact_size->width(); + gesture_event->data.show_press.height = + gesture_data->contact_size->height(); + break; + case blink::WebInputEvent::Type::kGestureTap: + gesture_event->data.tap.width = gesture_data->contact_size->width(); + gesture_event->data.tap.height = gesture_data->contact_size->height(); + break; + case blink::WebInputEvent::Type::kGestureLongPress: + gesture_event->data.long_press.width = + gesture_data->contact_size->width(); + gesture_event->data.long_press.height = + gesture_data->contact_size->height(); + break; + + case blink::WebInputEvent::Type::kGestureTwoFingerTap: + gesture_event->data.two_finger_tap.first_finger_width = + gesture_data->contact_size->width(); + gesture_event->data.two_finger_tap.first_finger_height = + gesture_data->contact_size->height(); + break; + case blink::WebInputEvent::Type::kGestureScrollBegin: + gesture_event->data.scroll_begin.delta_x_hint = + gesture_data->scroll_data->delta_x; + gesture_event->data.scroll_begin.delta_y_hint = + gesture_data->scroll_data->delta_y; + gesture_event->data.scroll_begin.delta_hint_units = + gesture_data->scroll_data->delta_units; + gesture_event->data.scroll_begin.target_viewport = + gesture_data->scroll_data->target_viewport; + gesture_event->data.scroll_begin.inertial_phase = + gesture_data->scroll_data->inertial_phase; + gesture_event->data.scroll_begin.synthetic = + gesture_data->scroll_data->synthetic; + gesture_event->data.scroll_begin.pointer_count = + gesture_data->scroll_data->pointer_count; + break; + case blink::WebInputEvent::Type::kGestureScrollEnd: + gesture_event->data.scroll_end.delta_units = + gesture_data->scroll_data->delta_units; + gesture_event->data.scroll_end.inertial_phase = + gesture_data->scroll_data->inertial_phase; + gesture_event->data.scroll_end.synthetic = + gesture_data->scroll_data->synthetic; + break; + case blink::WebInputEvent::Type::kGestureScrollUpdate: + gesture_event->data.scroll_update.delta_x = + gesture_data->scroll_data->delta_x; + gesture_event->data.scroll_update.delta_y = + gesture_data->scroll_data->delta_y; + gesture_event->data.scroll_update.delta_units = + gesture_data->scroll_data->delta_units; + gesture_event->data.scroll_update.inertial_phase = + gesture_data->scroll_data->inertial_phase; + if (gesture_data->scroll_data->update_details) { + gesture_event->data.scroll_update.velocity_x = + gesture_data->scroll_data->update_details->velocity_x; + gesture_event->data.scroll_update.velocity_y = + gesture_data->scroll_data->update_details->velocity_y; + gesture_event->data.scroll_update + .previous_update_in_sequence_prevented = + gesture_data->scroll_data->update_details + ->previous_update_in_sequence_prevented; + gesture_event->data.scroll_update.prevent_propagation = + gesture_data->scroll_data->update_details->prevent_propagation; + } + break; + } + } + + if (gesture_data->scroll_data) { + switch (type) { + default: + break; + case blink::WebInputEvent::Type::kGestureScrollBegin: + gesture_event->data.scroll_begin.delta_x_hint = + gesture_data->scroll_data->delta_x; + gesture_event->data.scroll_begin.delta_y_hint = + gesture_data->scroll_data->delta_y; + gesture_event->data.scroll_begin.delta_hint_units = + gesture_data->scroll_data->delta_units; + gesture_event->data.scroll_begin.target_viewport = + gesture_data->scroll_data->target_viewport; + gesture_event->data.scroll_begin.inertial_phase = + gesture_data->scroll_data->inertial_phase; + gesture_event->data.scroll_begin.synthetic = + gesture_data->scroll_data->synthetic; + gesture_event->data.scroll_begin.pointer_count = + gesture_data->scroll_data->pointer_count; + break; + case blink::WebInputEvent::Type::kGestureScrollEnd: + gesture_event->data.scroll_end.delta_units = + gesture_data->scroll_data->delta_units; + gesture_event->data.scroll_end.inertial_phase = + gesture_data->scroll_data->inertial_phase; + gesture_event->data.scroll_end.synthetic = + gesture_data->scroll_data->synthetic; + break; + case blink::WebInputEvent::Type::kGestureScrollUpdate: + gesture_event->data.scroll_update.delta_x = + gesture_data->scroll_data->delta_x; + gesture_event->data.scroll_update.delta_y = + gesture_data->scroll_data->delta_y; + gesture_event->data.scroll_update.delta_units = + gesture_data->scroll_data->delta_units; + gesture_event->data.scroll_update.inertial_phase = + gesture_data->scroll_data->inertial_phase; + if (gesture_data->scroll_data->update_details) { + gesture_event->data.scroll_update.velocity_x = + gesture_data->scroll_data->update_details->velocity_x; + gesture_event->data.scroll_update.velocity_y = + gesture_data->scroll_data->update_details->velocity_y; + gesture_event->data.scroll_update + .previous_update_in_sequence_prevented = + gesture_data->scroll_data->update_details + ->previous_update_in_sequence_prevented; + gesture_event->data.scroll_update.prevent_propagation = + gesture_data->scroll_data->update_details->prevent_propagation; + } + break; + } + } + + if (gesture_data->fling_data) { + switch (type) { + default: + break; + case blink::WebInputEvent::Type::kGestureFlingStart: + gesture_event->data.fling_start.velocity_x = + gesture_data->fling_data->velocity_x; + gesture_event->data.fling_start.velocity_y = + gesture_data->fling_data->velocity_y; + gesture_event->data.fling_start.target_viewport = + gesture_data->fling_data->target_viewport; + break; + case blink::WebInputEvent::Type::kGestureFlingCancel: + gesture_event->data.fling_cancel.target_viewport = + gesture_data->fling_data->target_viewport; + gesture_event->data.fling_cancel.prevent_boosting = + gesture_data->fling_data->prevent_boosting; + break; + } + } + + if (gesture_data->pinch_data && + type == blink::WebInputEvent::Type::kGesturePinchUpdate) { + gesture_event->data.pinch_update.zoom_disabled = + gesture_data->pinch_data->zoom_disabled; + gesture_event->data.pinch_update.scale = gesture_data->pinch_data->scale; + } + } else if (blink::WebInputEvent::IsTouchEventType(type)) { + content::mojom::TouchDataPtr touch_data; + if (!event.ReadTouchData<content::mojom::TouchDataPtr>(&touch_data)) + return false; + + (*out)->web_event.reset(new blink::WebTouchEvent( + type, event.modifiers(), event.timestamp_seconds())); + + blink::WebTouchEvent* touch_event = + static_cast<blink::WebTouchEvent*>((*out)->web_event.get()); + std::vector<content::mojom::TouchPointPtr> touches; + unsigned i; + for (i = 0; i < touch_data->touches.size() && + i < blink::WebTouchEvent::kTouchesLengthCap; + ++i) { + blink::WebTouchPoint& touch_point = touch_event->touches[i]; + TouchPointPropertiesFromPointerData(touch_data->touches[i], &touch_point); + } + + touch_event->touches_length = i; + touch_event->dispatch_type = touch_data->cancelable; + touch_event->moved_beyond_slop_region = + touch_data->moved_beyond_slop_region; + touch_event->touch_start_or_first_touch_move = + touch_data->touch_start_or_first_move; + touch_event->unique_touch_event_id = touch_data->unique_touch_event_id; + } else if (blink::WebInputEvent::IsMouseEventType(type) || + type == blink::WebInputEvent::Type::kMouseWheel) { + content::mojom::PointerDataPtr pointer_data; + if (!event.ReadPointerData<content::mojom::PointerDataPtr>(&pointer_data)) + return false; + + if (blink::WebInputEvent::IsMouseEventType(type)) { + (*out)->web_event.reset(new blink::WebMouseEvent( + type, event.modifiers(), event.timestamp_seconds())); + } else { + (*out)->web_event.reset(new blink::WebMouseWheelEvent( + type, event.modifiers(), event.timestamp_seconds())); + } + + blink::WebMouseEvent* mouse_event = + static_cast<blink::WebMouseEvent*>((*out)->web_event.get()); + + MouseEventPropertiesFromPointerData(pointer_data, mouse_event); + if (pointer_data->mouse_data) { + mouse_event->click_count = pointer_data->mouse_data->click_count; + + if (type == blink::WebInputEvent::Type::kMouseWheel && + pointer_data->mouse_data->wheel_data) { + blink::WebMouseWheelEvent* wheel_event = + static_cast<blink::WebMouseWheelEvent*>(mouse_event); + content::mojom::WheelDataPtr& wheel_data = + pointer_data->mouse_data->wheel_data; + wheel_event->delta_x = wheel_data->delta_x; + wheel_event->delta_y = wheel_data->delta_y; + wheel_event->wheel_ticks_x = wheel_data->wheel_ticks_x; + wheel_event->wheel_ticks_y = wheel_data->wheel_ticks_y; + wheel_event->acceleration_ratio_x = wheel_data->acceleration_ratio_x; + wheel_event->acceleration_ratio_y = wheel_data->acceleration_ratio_y; + wheel_event->resending_plugin_id = wheel_data->resending_plugin_id; + wheel_event->phase = + static_cast<blink::WebMouseWheelEvent::Phase>(wheel_data->phase); + wheel_event->momentum_phase = + static_cast<blink::WebMouseWheelEvent::Phase>( + wheel_data->momentum_phase); + wheel_event->scroll_by_page = wheel_data->scroll_by_page; + wheel_event->has_precise_scrolling_deltas = + wheel_data->has_precise_scrolling_deltas; + wheel_event->dispatch_type = wheel_data->cancelable; + } + } + + } else { + return false; + } + + return event.ReadLatency(&((*out)->latency_info)); +} + +void* StructTraits<content::mojom::EventDataView, + InputEventUniquePtr>::SetUpContext(const InputEventUniquePtr& + event) { + InputEventSerializationContext* context = + new InputEventSerializationContext(); + + if (!event->web_event) + return context; + + if (blink::WebInputEvent::IsKeyboardEventType(event->web_event->GetType())) { + const blink::WebKeyboardEvent* key_event = + static_cast<const blink::WebKeyboardEvent*>(event->web_event.get()); + context->key_data = content::mojom::KeyData::New( + key_event->dom_key, key_event->dom_code, key_event->windows_key_code, + key_event->native_key_code, key_event->is_system_key, + key_event->is_browser_shortcut, key_event->text, + key_event->unmodified_text); + return context; + } + if (blink::WebInputEvent::IsGestureEventType(event->web_event->GetType())) { + const blink::WebGestureEvent* gesture_event = + static_cast<const blink::WebGestureEvent*>(event->web_event.get()); + + context->gesture_data = content::mojom::GestureData::New(); + content::mojom::GestureDataPtr& gesture_data = context->gesture_data; + gesture_data->screen_position = gesture_event->PositionInScreen(); + gesture_data->widget_position = gesture_event->PositionInWidget(); + gesture_data->source_device = gesture_event->source_device; + gesture_data->unique_touch_event_id = gesture_event->unique_touch_event_id; + gesture_data->resending_plugin_id = gesture_event->resending_plugin_id; + + switch (gesture_event->GetType()) { + default: + break; + case blink::WebInputEvent::Type::kGestureTapDown: + gesture_data->contact_size = + gfx::Size(gesture_event->data.tap_down.width, + gesture_event->data.tap_down.height); + break; + case blink::WebInputEvent::Type::kGestureShowPress: + gesture_data->contact_size = + gfx::Size(gesture_event->data.show_press.width, + gesture_event->data.show_press.height); + break; + case blink::WebInputEvent::Type::kGestureTap: + case blink::WebInputEvent::Type::kGestureTapUnconfirmed: + case blink::WebInputEvent::Type::kGestureDoubleTap: + gesture_data->contact_size = gfx::Size(gesture_event->data.tap.width, + gesture_event->data.tap.height); + gesture_data->tap_data = + content::mojom::TapData::New(gesture_event->data.tap.tap_count); + break; + case blink::WebInputEvent::Type::kGestureLongPress: + gesture_data->contact_size = + gfx::Size(gesture_event->data.long_press.width, + gesture_event->data.long_press.height); + break; + + case blink::WebInputEvent::Type::kGestureTwoFingerTap: + gesture_data->contact_size = + gfx::Size(gesture_event->data.two_finger_tap.first_finger_width, + gesture_event->data.two_finger_tap.first_finger_height); + break; + case blink::WebInputEvent::Type::kGestureScrollBegin: + gesture_data->scroll_data = content::mojom::ScrollData::New( + gesture_event->data.scroll_begin.delta_x_hint, + gesture_event->data.scroll_begin.delta_y_hint, + gesture_event->data.scroll_begin.delta_hint_units, + gesture_event->data.scroll_begin.target_viewport, + gesture_event->data.scroll_begin.inertial_phase, + gesture_event->data.scroll_begin.synthetic, + gesture_event->data.scroll_begin.pointer_count, nullptr); + break; + case blink::WebInputEvent::Type::kGestureScrollEnd: + gesture_data->scroll_data = content::mojom::ScrollData::New( + 0, 0, gesture_event->data.scroll_end.delta_units, false, + gesture_event->data.scroll_end.inertial_phase, + gesture_event->data.scroll_end.synthetic, 0, nullptr); + break; + case blink::WebInputEvent::Type::kGestureScrollUpdate: + gesture_data->scroll_data = content::mojom::ScrollData::New( + gesture_event->data.scroll_update.delta_x, + gesture_event->data.scroll_update.delta_y, + gesture_event->data.scroll_update.delta_units, false, + gesture_event->data.scroll_update.inertial_phase, false, 0, + content::mojom::ScrollUpdate::New( + gesture_event->data.scroll_update.velocity_x, + gesture_event->data.scroll_update.velocity_y, + gesture_event->data.scroll_update + .previous_update_in_sequence_prevented, + gesture_event->data.scroll_update.prevent_propagation)); + break; + case blink::WebInputEvent::Type::kGestureFlingStart: + gesture_data->fling_data = content::mojom::FlingData::New( + gesture_event->data.fling_start.velocity_x, + gesture_event->data.fling_start.velocity_y, + gesture_event->data.fling_start.target_viewport, false); + break; + case blink::WebInputEvent::Type::kGestureFlingCancel: + gesture_data->fling_data = content::mojom::FlingData::New( + 0, 0, gesture_event->data.fling_cancel.target_viewport, + gesture_event->data.fling_cancel.prevent_boosting); + break; + case blink::WebInputEvent::Type::kGesturePinchUpdate: + gesture_data->pinch_data = content::mojom::PinchData::New( + gesture_event->data.pinch_update.zoom_disabled, + gesture_event->data.pinch_update.scale); + break; + } + return context; + } + if (blink::WebInputEvent::IsTouchEventType(event->web_event->GetType())) { + const blink::WebTouchEvent* touch_event = + static_cast<const blink::WebTouchEvent*>(event->web_event.get()); + + context->touch_data = content::mojom::TouchData::New( + touch_event->dispatch_type, touch_event->moved_beyond_slop_region, + touch_event->touch_start_or_first_touch_move, + touch_event->unique_touch_event_id, + std::vector<content::mojom::TouchPointPtr>()); + + for (unsigned i = 0; i < touch_event->touches_length; ++i) { + content::mojom::PointerDataPtr pointer_data = + PointerDataFromPointerProperties(touch_event->touches[i], nullptr); + context->touch_data->touches.emplace_back(content::mojom::TouchPoint::New( + touch_event->touches[i].state, touch_event->touches[i].radius_x, + touch_event->touches[i].radius_y, + touch_event->touches[i].rotation_angle, std::move(pointer_data))); + } + + return context; + } + + bool is_wheel_event = + event->web_event->GetType() == blink::WebInputEvent::Type::kMouseWheel; + if (blink::WebInputEvent::IsMouseEventType(event->web_event->GetType()) || + is_wheel_event) { + const blink::WebMouseEvent* mouse_event = + static_cast<const blink::WebMouseEvent*>(event->web_event.get()); + + content::mojom::WheelDataPtr wheel_data; + if (is_wheel_event) { + const blink::WebMouseWheelEvent* wheel_event = + static_cast<const blink::WebMouseWheelEvent*>(mouse_event); + wheel_data = content::mojom::WheelData::New( + wheel_event->delta_x, wheel_event->delta_y, + wheel_event->wheel_ticks_x, wheel_event->wheel_ticks_y, + wheel_event->acceleration_ratio_x, wheel_event->acceleration_ratio_y, + wheel_event->resending_plugin_id, wheel_event->phase, + wheel_event->momentum_phase, wheel_event->scroll_by_page, + wheel_event->has_precise_scrolling_deltas, + wheel_event->dispatch_type); + } + + context->pointer_data = PointerDataFromPointerProperties( + *mouse_event, content::mojom::MouseData::New(mouse_event->click_count, + std::move(wheel_data))); + return context; + } + + return context; +} + +void StructTraits<content::mojom::EventDataView, InputEventUniquePtr>:: + TearDownContext(const InputEventUniquePtr& event, void* context) { + delete static_cast<InputEventSerializationContext*>(context); +} + +StructTraits<content::mojom::EventDataView, InputEventUniquePtr>:: + InputEventSerializationContext::InputEventSerializationContext() {} + +StructTraits<content::mojom::EventDataView, InputEventUniquePtr>:: + InputEventSerializationContext::~InputEventSerializationContext() {} + +} // namespace mojo
diff --git a/content/common/input/input_event_struct_traits.h b/content/common/input/input_event_struct_traits.h new file mode 100644 index 0000000..9237448 --- /dev/null +++ b/content/common/input/input_event_struct_traits.h
@@ -0,0 +1,78 @@ +// 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 CONTENT_COMMON_INPUT_INPUT_EVENT_STRUCT_TRAITS_H_ +#define CONTENT_COMMON_INPUT_INPUT_EVENT_STRUCT_TRAITS_H_ + +#include "content/common/input/input_handler.mojom.h" + +namespace content { +class InputEvent; +} + +namespace mojo { + +using InputEventUniquePtr = std::unique_ptr<content::InputEvent>; + +template <> +struct StructTraits<content::mojom::EventDataView, InputEventUniquePtr> { + static blink::WebInputEvent::Type type(const InputEventUniquePtr& event) { + return event->web_event->GetType(); + } + + static int32_t modifiers(const InputEventUniquePtr& event) { + return event->web_event->GetModifiers(); + } + + static double timestamp_seconds(const InputEventUniquePtr& event) { + return event->web_event->TimeStampSeconds(); + } + + static const ui::LatencyInfo& latency(const InputEventUniquePtr& event) { + return event->latency_info; + } + + static const content::mojom::KeyDataPtr& key_data( + const InputEventUniquePtr& event, + void* context) { + return static_cast<InputEventSerializationContext*>(context)->key_data; + } + + static const content::mojom::PointerDataPtr& pointer_data( + const InputEventUniquePtr& event, + void* context) { + return static_cast<InputEventSerializationContext*>(context)->pointer_data; + } + + static const content::mojom::GestureDataPtr& gesture_data( + const InputEventUniquePtr& event, + void* context) { + return static_cast<InputEventSerializationContext*>(context)->gesture_data; + } + + static const content::mojom::TouchDataPtr& touch_data( + const InputEventUniquePtr& event, + void* context) { + return static_cast<InputEventSerializationContext*>(context)->touch_data; + } + + static bool Read(content::mojom::EventDataView r, InputEventUniquePtr* out); + static void* SetUpContext(const InputEventUniquePtr& handle); + static void TearDownContext(const InputEventUniquePtr& handle, void* context); + + private: + struct InputEventSerializationContext { + content::mojom::KeyDataPtr key_data; + content::mojom::GestureDataPtr gesture_data; + content::mojom::PointerDataPtr pointer_data; + content::mojom::TouchDataPtr touch_data; + + InputEventSerializationContext(); + ~InputEventSerializationContext(); + }; +}; + +} // namespace mojo + +#endif // CONTENT_COMMON_INPUT_INPUT_EVENT_STRUCT_TRAITS_H_
diff --git a/content/common/native_types.typemap b/content/common/native_types.typemap index 9a14d13..94240ef 100644 --- a/content/common/native_types.typemap +++ b/content/common/native_types.typemap
@@ -29,6 +29,7 @@ traits_headers = [ "//content/common/frame_messages.h", "//content/common/input_messages.h", + "//content/common/input/input_event_struct_traits.h", "//content/common/view_messages.h", "//content/public/common/common_param_traits.h", ] @@ -58,6 +59,7 @@ "content.mojom.Cancelability=blink::WebInputEvent::DispatchType", "content.mojom.EffectiveConnectionType=net::EffectiveConnectionType", "content.mojom.EditCommand=content::EditCommand", + "content.mojom.Event=std::unique_ptr<content::InputEvent>[move_only]", "content.mojom.EventType=blink::WebInputEvent::Type", "content.mojom.FrameOwnerProperties=content::FrameOwnerProperties", "content.mojom.FrameReplicationState=content::FrameReplicationState",
diff --git a/content/common/render_message_filter.mojom b/content/common/render_message_filter.mojom index 5a7da2f4e..720032d 100644 --- a/content/common/render_message_filter.mojom +++ b/content/common/render_message_filter.mojom
@@ -5,7 +5,9 @@ module content.mojom; import "cc/ipc/shared_bitmap_allocation_notifier.mojom"; +import "content/common/input/input_handler.mojom"; import "content/common/native_types.mojom"; +import "content/common/widget.mojom"; interface RenderMessageFilter { // Synchronously generates a new routing ID for the caller. @@ -13,11 +15,11 @@ // Similar to CreateWindow, except used for sub-widgets, like <select> // dropdowns. - [Sync] CreateNewWidget(int32 opener_id, content.mojom.WebPopupType popup_type) + [Sync] CreateNewWidget(int32 opener_id, content.mojom.WebPopupType popup_type, Widget widget) => (int32 route_id); // Similar to CreateWidget except the widget is a full screen window. - [Sync] CreateFullscreenWidget(int32 opener_id) + [Sync] CreateFullscreenWidget(int32 opener_id, Widget widget) => (int32 route_id); GetSharedBitmapAllocationNotifier(
diff --git a/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h b/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h deleted file mode 100644 index 79a5d44..0000000 --- a/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_COMMON_SANDBOX_LINUX_ANDROID_SANDBOX_BPF_BASE_POLICY_ANDROID_H_ -#define CONTENT_COMMON_SANDBOX_LINUX_ANDROID_SANDBOX_BPF_BASE_POLICY_ANDROID_H_ - -#include <sys/types.h> - -#include "base/macros.h" -#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h" - -namespace content { - -// This class builds on top of the generic Linux baseline policy to reduce -// Linux kernel attack surface. It augments the list of allowed syscalls to -// allow ones required by the Android runtime. -class SandboxBPFBasePolicyAndroid : public SandboxBPFBasePolicy { - public: - SandboxBPFBasePolicyAndroid(); - ~SandboxBPFBasePolicyAndroid() override; - - // sandbox::SandboxBPFPolicy: - sandbox::bpf_dsl::ResultExpr EvaluateSyscall( - int system_call_number) const override; - - private: - const pid_t pid_; - - DISALLOW_COPY_AND_ASSIGN(SandboxBPFBasePolicyAndroid); -}; - -} // namespace content - -#endif // CONTENT_COMMON_SANDBOX_LINUX_ANDROID_SANDBOX_BPF_BASE_POLICY_ANDROID_H_
diff --git a/content/common/widget.mojom b/content/common/widget.mojom new file mode 100644 index 0000000..a6013b4e --- /dev/null +++ b/content/common/widget.mojom
@@ -0,0 +1,13 @@ +// 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. + +module content.mojom; + +import "content/common/input/input_handler.mojom"; + +// Interface representing the Widget. +interface Widget { + // TODO(dtapuska): Implementation pending. crbug.com/722928. + // GetWidgetInputHandler(WidgetInputHandler& request); +};
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index f7b899e9..5a7ca4c 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -368,12 +368,6 @@ } @Override - public String getUrl() { - if (isDestroyed()) return null; - return nativeGetURL(mNativeWebContentsAndroid); - } - - @Override public String getLastCommittedUrl() { return nativeGetLastCommittedURL(mNativeWebContentsAndroid); } @@ -664,7 +658,6 @@ private native void nativeSelectWordAroundCaret(long nativeWebContentsAndroid); private native void nativeAdjustSelectionByCharacterOffset( long nativeWebContentsAndroid, int startAdjust, int endAdjust); - private native String nativeGetURL(long nativeWebContentsAndroid); private native String nativeGetLastCommittedURL(long nativeWebContentsAndroid); private native boolean nativeIsIncognito(long nativeWebContentsAndroid); private native void nativeResumeLoadingCreatedWebContents(long nativeWebContentsAndroid);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java index 4a0bcc23..f172b22 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -238,13 +238,6 @@ public void adjustSelectionByCharacterOffset(int startAdjust, int endAdjust); /** - * Get the URL of the current page. - * - * @return The URL of the current page. - */ - String getUrl(); - - /** * Gets the last committed URL. It represents the current page that is * displayed in this WebContents. It represents the current security context. *
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index 3d35612..df20d008 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -630,7 +630,7 @@ private void reloadPage() throws Throwable { // Reload the page, then focus will be lost and keyboard should be hidden. - mRule.fullyLoadUrl(mRule.getContentViewCore().getWebContents().getUrl()); + mRule.fullyLoadUrl(mRule.getContentViewCore().getWebContents().getLastCommittedUrl()); } @Test
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 989f45a..820f611 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -19,7 +19,6 @@ "blink::mojom::BackgroundFetchService", "blink::mojom::BackgroundSyncService", "blink::mojom::BroadcastChannelProvider", - "blink::mojom::BudgetService", "blink::mojom::Hyphenation", "blink::mojom::MimeRegistry", "blink::mojom::NotificationService",
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json index 27b37ef..52a453ba 100644 --- a/content/public/app/mojo/content_renderer_manifest.json +++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -44,6 +44,7 @@ "blink::mojom::ManifestManager", "content::mojom::ImageDownloader", "content::mojom::FrameInputHandler", + "content::mojom::Widget", "mojom::MediaDevicesListener" ] },
diff --git a/content/public/browser/resource_dispatcher_host_delegate.cc b/content/public/browser/resource_dispatcher_host_delegate.cc index 8b1a59c..94b7755 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.cc +++ b/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -88,7 +88,8 @@ PreviewsState ResourceDispatcherHostDelegate::GetPreviewsState( const net::URLRequest& url_request, - content::ResourceContext* resource_context) { + content::ResourceContext* resource_context, + PreviewsState previews_to_allow) { return PREVIEWS_UNSPECIFIED; }
diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h index c3c96991..8a5a133 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.h +++ b/content/public/browser/resource_dispatcher_host_delegate.h
@@ -126,10 +126,13 @@ // Asks the embedder for the PreviewsState which says which previews should // be enabled for the given request. The PreviewsState is a bitmask of // potentially several Previews optimizations. It is only called for requests - // with an unspecified Previews state. + // with an unspecified Previews state. If previews_to_allow is set to + // anything other than PREVIEWS_UNSPECIFIED, it is taken as a limit on + // available preview states. virtual PreviewsState GetPreviewsState( const net::URLRequest& url_request, - content::ResourceContext* resource_context); + content::ResourceContext* resource_context, + PreviewsState previews_to_allow); // Asks the embedder for NavigationData related to this request. It is only // called for navigation requests.
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 05d3fe14..5aa1a16a 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h
@@ -18,6 +18,7 @@ #include "content/public/browser/invalidate_type.h" #include "content/public/browser/web_contents.h" #include "content/public/common/media_stream_request.h" +#include "content/public/common/previews_state.h" #include "content/public/common/window_container_type.mojom.h" #include "third_party/WebKit/public/platform/WebDisplayMode.h" #include "third_party/WebKit/public/platform/WebDragOperation.h" @@ -566,6 +567,10 @@ const url::Origin& origin, const GURL& resource_url); + // Give WebContentsDelegates the opportunity to adjust the previews state. + virtual void AdjustPreviewsStateForNavigation(PreviewsState* previews_state) { + } + protected: virtual ~WebContentsDelegate();
diff --git a/content/public/common/previews_state.h b/content/public/common/previews_state.h index 4559261..77bf8fc 100644 --- a/content/public/common/previews_state.h +++ b/content/public/common/previews_state.h
@@ -40,6 +40,10 @@ PREVIEWS_STATE_LAST = PREVIEWS_OFF }; +// Combination of all previews that are guaranteed not to provide partial +// content. +const PreviewsState PARTIAL_CONTENT_SAFE_PREVIEWS = SERVER_LOFI_ON; + // Ensure that content::PreviewsState and blink::WebURLRequest::PreviewsState // are kept in sync. STATIC_ASSERT_PREVIEWS_ENUM(PREVIEWS_UNSPECIFIED,
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/HistoryUtils.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/HistoryUtils.java index 8047718..71d42cfe 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/HistoryUtils.java +++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/HistoryUtils.java
@@ -100,11 +100,11 @@ } /** - * Calls {@link NavigationController#getHostname()} on UI Thread to get the current URL. + * Calls {@link WebContents#getLastCommittedUrl()} on UI Thread to get the current URL. * * @param instrumentation an Instrumentation instance. * @param contentViewCore a ContentViewCore instance. - * @return the URL of the current page + * @return the last committed URL of the provided ContentViewCore. * @throws Throwable */ public static String getUrlOnUiThread(Instrumentation instrumentation, @@ -113,7 +113,7 @@ instrumentation, new Callable<String>() { @Override public String call() throws Exception { - return webContents.getUrl(); + return webContents.getLastCommittedUrl(); } }); }
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index ec91284..b88b61ff 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -26,6 +26,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_manager.h" #include "content/browser/accessibility/browser_accessibility.h" @@ -1319,7 +1320,7 @@ SurfaceHitTestReadyNotifier::SurfaceHitTestReadyNotifier( RenderWidgetHostViewBase* target_view) : target_view_(target_view) { - surface_manager_ = GetSurfaceManager(); + surface_manager_ = GetFrameSinkManager()->surface_manager(); } void SurfaceHitTestReadyNotifier::WaitForSurfaceReady(
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 432d781c..886a353 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -40,6 +40,7 @@ void CreateNewWidget(int32_t opener_id, blink::WebPopupType popup_type, + mojom::WidgetPtr widget, CreateNewWidgetCallback callback) override { // See comment in CreateNewWindow(). NOTREACHED(); @@ -47,6 +48,7 @@ bool CreateNewWidget(int32_t opener_id, blink::WebPopupType popup_type, + mojom::WidgetPtr widget, int32_t* route_id) override { thread_->OnCreateWidget(opener_id, popup_type, route_id); return true; @@ -54,6 +56,7 @@ void CreateFullscreenWidget( int opener_id, + mojom::WidgetPtr widget, CreateFullscreenWidgetCallback callback) override { NOTREACHED(); }
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc index 6867290..b15489d 100644 --- a/content/public/test/navigation_simulator.cc +++ b/content/public/test/navigation_simulator.cc
@@ -16,6 +16,7 @@ #include "content/public/common/resource_request_body.h" #include "content/test/test_navigation_url_loader.h" #include "content/test/test_render_frame_host.h" +#include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/url_request/redirect_info.h" @@ -98,6 +99,7 @@ render_frame_host_(render_frame_host), handle_(nullptr), navigation_url_(original_url), + socket_address_("2001:db8::1", 80), weak_factory_(this) { if (render_frame_host->GetParent()) { if (!render_frame_host->frame_tree_node()->has_committed_real_load()) @@ -318,8 +320,7 @@ params.contents_mime_type = "text/html"; params.method = "GET"; params.http_status_code = 200; - params.socket_address.set_host("2001:db8::1"); - params.socket_address.set_port(80); + params.socket_address = socket_address_; params.history_list_was_cleared = false; params.original_request_url = navigation_url_; params.was_within_same_document = false; @@ -450,8 +451,7 @@ params.contents_mime_type = "text/html"; params.method = "GET"; params.http_status_code = 200; - params.socket_address.set_host("2001:db8::1"); - params.socket_address.set_port(80); + params.socket_address = socket_address_; params.history_list_was_cleared = false; params.original_request_url = navigation_url_; params.was_within_same_document = true; @@ -484,6 +484,13 @@ referrer_ = referrer; } +void NavigationSimulator::SetSocketAddress( + const net::HostPortPair& socket_address) { + CHECK_LE(state_, STARTED) << "The socket address cannot be set after the " + "navigation has committed or failed"; + socket_address_ = socket_address; +} + NavigationThrottle::ThrottleCheckResult NavigationSimulator::GetLastThrottleCheckResult() { return last_throttle_check_result_.value();
diff --git a/content/public/test/navigation_simulator.h b/content/public/test/navigation_simulator.h index 86e15c1..da5ea4a6 100644 --- a/content/public/test/navigation_simulator.h +++ b/content/public/test/navigation_simulator.h
@@ -14,6 +14,7 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/common/referrer.h" #include "content/public/test/navigation_simulator.h" +#include "net/base/host_port_pair.h" #include "ui/base/page_transition_types.h" class GURL; @@ -129,9 +130,7 @@ // -------------------------------------------------------------------------- // The following functions are used to specify the parameters of the - // navigation. Changes should be made before calling |Start|, unless they are - // meant to apply to a redirect. In that case, they should be made before - // calling |Redirect|. + // navigation. // The following parameters are constant during the navigation and may only be // specified before calling |Start|. @@ -143,6 +142,12 @@ // |Redirect|. virtual void SetReferrer(const Referrer& referrer); + // The following parameters can change at any point until the page fails or + // commits. They should be specified before calling |Fail| or |Commit|. + virtual void SetSocketAddress(const net::HostPortPair& socket_address); + + // -------------------------------------------------------------------------- + // Gets the last throttle check result computed by the navigation throttles. // It is an error to call this before Start() is called. virtual NavigationThrottle::ThrottleCheckResult GetLastThrottleCheckResult(); @@ -201,6 +206,7 @@ NavigationHandleImpl* handle_; GURL navigation_url_; + net::HostPortPair socket_address_; Referrer referrer_; ui::PageTransition transition_ = ui::PAGE_TRANSITION_LINK;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 580e320..ca2c49f 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -770,7 +770,6 @@ "//third_party/webrtc/api:video_frame_api", "//third_party/webrtc/api/audio_codecs:builtin_audio_decoder_factory", "//third_party/webrtc/api/audio_codecs:builtin_audio_encoder_factory", - "//third_party/webrtc/common_video:common_video", "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/media:rtc_media_base", "//third_party/webrtc/modules/audio_device",
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc index c007c2d..ad3f85ab 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -25,8 +25,8 @@ #include "cc/quads/surface_draw_quad.h" #include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/display.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" #include "content/common/android/sync_compositor_messages.h" #include "content/common/view_messages.h" #include "content/renderer/android/synchronous_compositor_filter.h" @@ -126,8 +126,8 @@ sender_(RenderThreadImpl::current()->sync_compositor_message_filter()), memory_policy_(0u), frame_swap_message_queue_(frame_swap_message_queue), - surface_manager_(new cc::SurfaceManager), - local_surface_id_allocator_(new cc::LocalSurfaceIdAllocator()), + frame_sink_manager_(new cc::FrameSinkManager), + local_surface_id_allocator_(new cc::LocalSurfaceIdAllocator), begin_frame_source_(std::move(begin_frame_source)) { DCHECK(registry_); DCHECK(sender_); @@ -177,10 +177,10 @@ constexpr bool handles_frame_sink_id_invalidation = true; constexpr bool needs_sync_points = true; root_support_ = cc::CompositorFrameSinkSupport::Create( - this, surface_manager_.get(), kRootFrameSinkId, root_support_is_root, + this, frame_sink_manager_.get(), kRootFrameSinkId, root_support_is_root, handles_frame_sink_id_invalidation, needs_sync_points); child_support_ = cc::CompositorFrameSinkSupport::Create( - this, surface_manager_.get(), kChildFrameSinkId, child_support_is_root, + this, frame_sink_manager_.get(), kChildFrameSinkId, child_support_is_root, handles_frame_sink_id_invalidation, needs_sync_points); cc::RendererSettings software_renderer_settings; @@ -200,7 +200,8 @@ shared_bitmap_manager_, nullptr /* gpu_memory_buffer_manager */, software_renderer_settings, kRootFrameSinkId, std::move(output_surface), nullptr /* scheduler */, nullptr /* texture_mailbox_deleter */)); - display_->Initialize(&display_client_, surface_manager_.get()); + display_->Initialize(&display_client_, + frame_sink_manager_->surface_manager()); display_->SetVisible(true); return true; } @@ -217,7 +218,7 @@ software_output_surface_ = nullptr; display_ = nullptr; local_surface_id_allocator_ = nullptr; - surface_manager_ = nullptr; + frame_sink_manager_ = nullptr; cc::LayerTreeFrameSink::DetachFromClient(); CancelFallbackTick(); }
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h index 19e9831..9b66c5b 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -30,8 +30,8 @@ class CompositorFrameSinkSupport; class ContextProvider; class Display; +class FrameSinkManager; class LocalSurfaceIdAllocator; -class SurfaceManager; } // namespace cc namespace IPC { @@ -153,19 +153,19 @@ // TODO(danakj): These don't to be stored in unique_ptrs when OutputSurface // is owned/destroyed on the compositor thread. - std::unique_ptr<cc::SurfaceManager> surface_manager_; + std::unique_ptr<cc::FrameSinkManager> frame_sink_manager_; std::unique_ptr<cc::LocalSurfaceIdAllocator> local_surface_id_allocator_; cc::LocalSurfaceId child_local_surface_id_; cc::LocalSurfaceId root_local_surface_id_; gfx::Size child_size_; gfx::Size display_size_; float device_scale_factor_ = 0; - // Uses surface_manager_. + // Uses frame_sink_manager_. std::unique_ptr<cc::CompositorFrameSinkSupport> root_support_; - // Uses surface_manager_. + // Uses frame_sink_manager_. std::unique_ptr<cc::CompositorFrameSinkSupport> child_support_; StubDisplayClient display_client_; - // Uses surface_manager_. + // Uses frame_sink_manager_. std::unique_ptr<cc::Display> display_; // Owned by |display_|. SoftwareOutputSurface* software_output_surface_ = nullptr;
diff --git a/content/renderer/media/gpu/rtc_video_encoder.cc b/content/renderer/media/gpu/rtc_video_encoder.cc index 8c671e5..2185d7e 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.cc +++ b/content/renderer/media/gpu/rtc_video_encoder.cc
@@ -47,16 +47,25 @@ DISALLOW_IMPLICIT_CONSTRUCTORS(RTCTimestamps); }; -webrtc::VideoCodecType ProfileToWebRtcVideoCodecType( - media::VideoCodecProfile profile) { - if (profile >= media::VP8PROFILE_MIN && profile <= media::VP8PROFILE_MAX) { - return webrtc::kVideoCodecVP8; - } else if (profile >= media::H264PROFILE_MIN && - profile <= media::H264PROFILE_MAX) { - return webrtc::kVideoCodecH264; +// Translate from webrtc::VideoCodecType and webrtc::VideoCodec to +// media::VideoCodecProfile. +media::VideoCodecProfile WebRTCVideoCodecToVideoCodecProfile( + webrtc::VideoCodecType type, + const webrtc::VideoCodec* codec_settings) { + DCHECK_EQ(type, codec_settings->codecType); + switch (type) { + case webrtc::kVideoCodecVP8: + return media::VP8PROFILE_ANY; + case webrtc::kVideoCodecVP9: + return media::VP9PROFILE_MIN; + case webrtc::kVideoCodecH264: + // TODO(magjed): WebRTC is only using Baseline profile for now. Update + // once http://crbug/webrtc/6337 is fixed. + return media::H264PROFILE_BASELINE; + default: + NOTREACHED() << "Unrecognized video codec type"; + return media::VIDEO_CODEC_PROFILE_UNKNOWN; } - NOTREACHED() << "Invalid profile " << GetProfileName(profile); - return webrtc::kVideoCodecUnknown; } // Populates struct webrtc::RTPFragmentationHeader for H264 codec. @@ -783,12 +792,12 @@ } RTCVideoEncoder::RTCVideoEncoder( - media::VideoCodecProfile profile, + webrtc::VideoCodecType type, media::GpuVideoAcceleratorFactories* gpu_factories) - : profile_(profile), + : video_codec_type_(type), gpu_factories_(gpu_factories), gpu_task_runner_(gpu_factories->GetTaskRunner()) { - DVLOG(1) << "RTCVideoEncoder(): profile=" << GetProfileName(profile); + DVLOG(1) << "RTCVideoEncoder(): codec type=" << type; } RTCVideoEncoder::~RTCVideoEncoder() { @@ -809,7 +818,9 @@ Release(); } - impl_ = new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_)); + impl_ = new Impl(gpu_factories_, video_codec_type_); + const media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile( + impl_->video_codec_type(), codec_settings); base::WaitableEvent initialization_waiter( base::WaitableEvent::ResetPolicy::MANUAL, @@ -817,14 +828,17 @@ int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED; gpu_task_runner_->PostTask( FROM_HERE, - base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, impl_, + base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, + impl_, gfx::Size(codec_settings->width, codec_settings->height), - codec_settings->startBitrate, profile_, &initialization_waiter, + codec_settings->startBitrate, + profile, + &initialization_waiter, &initialization_retval)); // webrtc::VideoEncoder expects this call to be synchronous. initialization_waiter.Wait(); - RecordInitEncodeUMA(initialization_retval, profile_); + RecordInitEncodeUMA(initialization_retval, profile); return initialization_retval; }
diff --git a/content/renderer/media/gpu/rtc_video_encoder.h b/content/renderer/media/gpu/rtc_video_encoder.h index 67d59b3..bef4f21c 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.h +++ b/content/renderer/media/gpu/rtc_video_encoder.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT RTCVideoEncoder : NON_EXPORTED_BASE(public webrtc::VideoEncoder) { public: - RTCVideoEncoder(media::VideoCodecProfile profile, + RTCVideoEncoder(webrtc::VideoCodecType type, media::GpuVideoAcceleratorFactories* gpu_factories); ~RTCVideoEncoder() override; @@ -68,7 +68,8 @@ void RecordInitEncodeUMA(int32_t init_retval, media::VideoCodecProfile profile); - const media::VideoCodecProfile profile_; + // The video codec type, as reported to WebRTC. + const webrtc::VideoCodecType video_codec_type_; // Factory for creating VEAs, shared memory buffers, etc. media::GpuVideoAcceleratorFactories* gpu_factories_;
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.cc b/content/renderer/media/gpu/rtc_video_encoder_factory.cc index bbece0d..f3189de 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.cc
@@ -11,23 +11,23 @@ #include "content/renderer/media/gpu/rtc_video_encoder.h" #include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h" #include "media/renderers/gpu_video_accelerator_factories.h" -#include "third_party/webrtc/common_video/h264/profile_level_id.h" +#include "media/video/video_encode_accelerator.h" namespace content { namespace { // Translate from media::VideoEncodeAccelerator::SupportedProfile to -// cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the -// profile isn't supported. -base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( +// one or more instances of cricket::WebRtcVideoEncoderFactory::VideoCodec +void VEAToWebRTCCodecs( + std::vector<cricket::VideoCodec>* codecs, const media::VideoEncodeAccelerator::SupportedProfile& profile) { DCHECK_EQ(profile.max_framerate_denominator, 1U); if (profile.profile >= media::VP8PROFILE_MIN && profile.profile <= media::VP8PROFILE_MAX) { if (base::FeatureList::IsEnabled(features::kWebRtcHWVP8Encoding)) { - return base::Optional<cricket::VideoCodec>(cricket::VideoCodec("VP8")); + codecs->push_back(cricket::VideoCodec("VP8")); } } else if (profile.profile >= media::H264PROFILE_MIN && profile.profile <= media::H264PROFILE_MAX) { @@ -41,41 +41,10 @@ #endif // BUILDFLAG(RTC_USE_H264) && !defined(MEDIA_DISABLE_FFMPEG) if (webrtc_h264_sw_enabled || base::FeatureList::IsEnabled(features::kWebRtcHWH264Encoding)) { - webrtc::H264::Profile h264_profile; - switch (profile.profile) { - case media::H264PROFILE_BASELINE: - h264_profile = webrtc::H264::kProfileBaseline; - break; - case media::H264PROFILE_MAIN: - h264_profile = webrtc::H264::kProfileMain; - break; - case media::H264PROFILE_HIGH: - h264_profile = webrtc::H264::kProfileHigh; - break; - default: - // Unsupported H264 profile in WebRTC. - return base::Optional<cricket::VideoCodec>(); - } - - const int width = profile.max_resolution.width(); - const int height = profile.max_resolution.height(); - const int fps = profile.max_framerate_numerator; - DCHECK_EQ(1u, profile.max_framerate_denominator); - - const rtc::Optional<webrtc::H264::Level> h264_level = - webrtc::H264::SupportedLevel(width * height, fps); - const webrtc::H264::ProfileLevelId profile_level_id( - h264_profile, h264_level.value_or(webrtc::H264::kLevel1)); - - cricket::VideoCodec codec("H264"); - codec.SetParam(cricket::kH264FmtpProfileLevelId, - *webrtc::H264::ProfileLevelIdToString(profile_level_id)); - codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); - codec.SetParam(cricket::kH264FmtpPacketizationMode, "1"); - return base::Optional<cricket::VideoCodec>(codec); + // TODO(magjed): Propagate H264 profile information. + codecs->push_back(cricket::VideoCodec("H264")); } } - return base::Optional<cricket::VideoCodec>(); } } // anonymous namespace @@ -85,36 +54,20 @@ : gpu_factories_(gpu_factories) { const media::VideoEncodeAccelerator::SupportedProfiles& profiles = gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles(); - for (const auto& profile : profiles) { - base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile); - if (codec) { - supported_codecs_.push_back(std::move(*codec)); - profiles_.push_back(profile.profile); - } - } - // There should be a 1:1 mapping between media::VideoCodecProfile and - // cricket::VideoCodec. - CHECK_EQ(profiles_.size(), supported_codecs_.size()); + for (const auto& profile : profiles) + VEAToWebRTCCodecs(&supported_codecs_, profile); } RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {} webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder( const cricket::VideoCodec& codec) { - for (size_t i = 0; i < supported_codecs_.size(); ++i) { - if (!cricket::CodecNamesEq(codec.name, supported_codecs_[i].name)) - continue; - // Check H264 profile. - using webrtc::H264::ParseSdpProfileLevelId; - if (cricket::CodecNamesEq(codec.name.c_str(), cricket::kH264CodecName) && - ParseSdpProfileLevelId(codec.params)->profile != - ParseSdpProfileLevelId(supported_codecs_[i].params)->profile) { - continue; + for (const cricket::VideoCodec& supported_codec : supported_codecs_) { + if (cricket::CodecNamesEq(codec.name, supported_codec.name)) { + webrtc::VideoCodecType type = webrtc::PayloadNameToCodecType(codec.name) + .value_or(webrtc::kVideoCodecUnknown); + return new RTCVideoEncoder(type, gpu_factories_); } - // There should be a 1:1 mapping between media::VideoCodecProfile and - // cricket::VideoCodec. - CHECK_EQ(profiles_.size(), supported_codecs_.size()); - return new RTCVideoEncoder(profiles_[i], gpu_factories_); } return nullptr; }
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.h b/content/renderer/media/gpu/rtc_video_encoder_factory.h index c5bcde0..307f8f92 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.h +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.h
@@ -39,9 +39,6 @@ media::GpuVideoAcceleratorFactories* gpu_factories_; // List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec. - // |profiles_| and |supported_codecs_| have the same length and the profile - // for |supported_codecs_[i]| is |profiles_[i]|. - std::vector<media::VideoCodecProfile> profiles_; std::vector<cricket::VideoCodec> supported_codecs_; DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
diff --git a/content/renderer/media/gpu/rtc_video_encoder_unittest.cc b/content/renderer/media/gpu/rtc_video_encoder_unittest.cc index 889b024..3fd7a91b 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_unittest.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_unittest.cc
@@ -113,19 +113,7 @@ void CreateEncoder(webrtc::VideoCodecType codec_type) { DVLOG(3) << __func__; - media::VideoCodecProfile media_profile; - switch (codec_type) { - case webrtc::kVideoCodecVP8: - media_profile = media::VP8PROFILE_ANY; - break; - case webrtc::kVideoCodecH264: - media_profile = media::H264PROFILE_BASELINE; - break; - default: - ADD_FAILURE() << "Unexpected codec type: " << codec_type; - media_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; - } - rtc_encoder_ = base::MakeUnique<RTCVideoEncoder>(media_profile, + rtc_encoder_ = base::MakeUnique<RTCVideoEncoder>(codec_type, mock_gpu_factories_.get()); }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 8bd2dbd..9255fbd 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1429,10 +1429,15 @@ if (render_view()->webview()) active_url = render_view()->GetURLForGraphicsContext3D(); + mojom::WidgetPtr widget_channel; + mojom::WidgetRequest widget_channel_request = + mojo::MakeRequest(&widget_channel); + // Synchronous IPC to obtain a routing id for the fullscreen widget. int32_t fullscreen_widget_routing_id = MSG_ROUTING_NONE; if (!RenderThreadImpl::current_render_message_filter() ->CreateFullscreenWidget(render_view()->routing_id(), + std::move(widget_channel), &fullscreen_widget_routing_id)) { return nullptr; } @@ -1443,7 +1448,7 @@ RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create( fullscreen_widget_routing_id, show_callback, GetRenderWidget()->compositor_deps(), plugin, active_url, - GetRenderWidget()->screen_info()); + GetRenderWidget()->screen_info(), std::move(widget_channel_request)); // TODO(nick): The show() handshake seems like unnecessary complexity here, // since there's no real delay between CreateFullscreenWidget and // ShowCreatedFullscreenWidget. Would it be simpler to have the
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 13bf677..7c43924 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -340,7 +340,8 @@ const ScreenInfo& screen_info, bool swapped_out, bool hidden, - bool never_visible) + bool never_visible, + mojom::WidgetRequest widget_request) : routing_id_(widget_routing_id), compositor_deps_(compositor_deps), webwidget_internal_(nullptr), @@ -381,6 +382,7 @@ time_to_first_active_paint_recorded_(true), was_shown_time_(base::TimeTicks::Now()), current_content_source_id_(0), + widget_binding_(this, std::move(widget_request)), weak_ptr_factory_(this) { DCHECK_NE(routing_id_, MSG_ROUTING_NONE); if (!swapped_out) @@ -431,16 +433,21 @@ CompositorDependencies* compositor_deps, blink::WebPopupType popup_type, const ScreenInfo& screen_info) { + mojom::WidgetPtr widget_channel; + mojom::WidgetRequest widget_channel_request = + mojo::MakeRequest(&widget_channel); + // Do a synchronous IPC to obtain a routing ID. int32_t routing_id = MSG_ROUTING_NONE; if (!RenderThreadImpl::current_render_message_filter()->CreateNewWidget( - opener->GetRoutingID(), popup_type, &routing_id)) { + opener->GetRoutingID(), popup_type, std::move(widget_channel), + &routing_id)) { return nullptr; } scoped_refptr<RenderWidget> widget( new RenderWidget(routing_id, compositor_deps, popup_type, screen_info, - false, false, false)); + false, false, false, std::move(widget_channel_request))); ShowCallback opener_callback = base::Bind(&RenderViewImpl::ShowCreatedPopupWidget, opener->GetWeakPtr()); widget->Init(opener_callback, RenderWidget::CreateWebWidget(widget.get()));
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 8f1d752..c9c67df4 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -31,6 +31,7 @@ #include "content/common/edit_command.h" #include "content/common/features.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/widget.mojom.h" #include "content/public/common/drop_data.h" #include "content/public/common/screen_info.h" #include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h" @@ -44,6 +45,7 @@ #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" #include "ipc/ipc_sender.h" +#include "mojo/public/cpp/bindings/binding.h" #include "third_party/WebKit/public/platform/WebDisplayMode.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebRect.h" @@ -128,6 +130,7 @@ : public IPC::Listener, public IPC::Sender, NON_EXPORTED_BASE(virtual public blink::WebWidgetClient), + public mojom::Widget, public RenderWidgetCompositorDelegate, public RenderWidgetInputHandlerDelegate, public RenderWidgetScreenMetricsEmulatorDelegate, @@ -446,7 +449,8 @@ const ScreenInfo& screen_info, bool swapped_out, bool hidden, - bool never_visible); + bool never_visible, + mojom::WidgetRequest widget_request = nullptr); ~RenderWidget() override; @@ -898,6 +902,8 @@ scoped_refptr<MainThreadEventQueue> input_event_queue_; + mojo::Binding<mojom::Widget> widget_binding_; + base::WeakPtrFactory<RenderWidget> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidget);
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index 3b646ee3..a40db586f 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -253,12 +253,14 @@ CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, const GURL& active_url, - const ScreenInfo& screen_info) { + const ScreenInfo& screen_info, + mojom::WidgetRequest widget_request) { DCHECK_NE(MSG_ROUTING_NONE, routing_id); DCHECK(!show_callback.is_null()); scoped_refptr<RenderWidgetFullscreenPepper> widget( new RenderWidgetFullscreenPepper(routing_id, compositor_deps, plugin, - active_url, screen_info)); + active_url, screen_info, + std::move(widget_request))); widget->Init(show_callback, new PepperWidget(widget.get())); widget->AddRef(); return widget.get(); @@ -269,14 +271,16 @@ CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, const GURL& active_url, - const ScreenInfo& screen_info) + const ScreenInfo& screen_info, + mojom::WidgetRequest widget_request) : RenderWidget(routing_id, compositor_deps, blink::kWebPopupTypeNone, screen_info, false, false, - false), + false, + std::move(widget_request)), active_url_(active_url), plugin_(plugin), layer_(NULL),
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h index 5aa2140..b5aef5c 100644 --- a/content/renderer/render_widget_fullscreen_pepper.h +++ b/content/renderer/render_widget_fullscreen_pepper.h
@@ -36,7 +36,8 @@ CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, const GURL& active_url, - const ScreenInfo& screen_info); + const ScreenInfo& screen_info, + mojom::WidgetRequest widget_request); // pepper::FullscreenContainer API. void Invalidate() override; @@ -61,7 +62,8 @@ CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, const GURL& active_url, - const ScreenInfo& screen_info); + const ScreenInfo& screen_info, + mojom::WidgetRequest widget_request); ~RenderWidgetFullscreenPepper() override; // RenderWidget API.
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index c4401340..09e8486 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/test/histogram_tester.h" +#include "base/test/scoped_task_environment.h" #include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input_messages.h" #include "content/common/resize_params.h" @@ -154,6 +155,7 @@ widget_->Release(); DCHECK(widget_->HasOneRef()); } + ~RenderWidgetUnittest() override {} InteractiveRenderWidget* widget() const { return widget_.get(); } @@ -162,6 +164,9 @@ return histogram_tester_; } + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + private: MockRenderProcess render_process_; MockRenderThread render_thread_; @@ -462,6 +467,9 @@ PopupRenderWidget* widget() const { return widget_.get(); } FakeCompositorDependencies compositor_deps_; + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + private: MockRenderProcess render_process_; MockRenderThread render_thread_;
diff --git a/content/renderer/renderer_main_platform_delegate_android.cc b/content/renderer/renderer_main_platform_delegate_android.cc index fd6dde5..ffcb0a7d 100644 --- a/content/renderer/renderer_main_platform_delegate_android.cc +++ b/content/renderer/renderer_main_platform_delegate_android.cc
@@ -14,8 +14,8 @@ #include "sandbox/sandbox_features.h" #if BUILDFLAG(USE_SECCOMP_BPF) -#include "content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h" #include "content/renderer/seccomp_sandbox_status_android.h" +#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.h" #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" #endif @@ -115,7 +115,7 @@ << "Seccomp sandbox"; } - sandbox::SandboxBPF sandbox(new SandboxBPFBasePolicyAndroid()); + sandbox::SandboxBPF sandbox(new sandbox::BaselinePolicyAndroid()); CHECK( sandbox.StartSandbox(sandbox::SandboxBPF::SeccompLevel::MULTI_THREADED));
diff --git a/content/shell/android/java/src/org/chromium/content_shell/Shell.java b/content/shell/android/java/src/org/chromium/content_shell/Shell.java index fb232075..63077b4 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/Shell.java +++ b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
@@ -170,7 +170,7 @@ mPrevButton.setVisibility(hasFocus ? GONE : VISIBLE); mStopReloadButton.setVisibility(hasFocus ? GONE : VISIBLE); if (!hasFocus) { - mUrlTextView.setText(mWebContents.getUrl()); + mUrlTextView.setText(mWebContents.getVisibleUrl()); } } }); @@ -195,7 +195,7 @@ public void loadUrl(String url) { if (url == null) return; - if (TextUtils.equals(url, mWebContents.getUrl())) { + if (TextUtils.equals(url, mWebContents.getLastCommittedUrl())) { mNavigationController.reload(true); } else { mNavigationController.loadUrl(new LoadUrlParams(sanitizeUrl(url))); @@ -301,8 +301,8 @@ mWebContents = mContentViewCore.getWebContents(); mNavigationController = mWebContents.getNavigationController(); if (getParent() != null) mContentViewCore.onShow(); - if (mWebContents.getUrl() != null) { - mUrlTextView.setText(mWebContents.getUrl()); + if (mWebContents.getVisibleUrl() != null) { + mUrlTextView.setText(mWebContents.getVisibleUrl()); } ((FrameLayout) findViewById(R.id.contentview_holder)).addView(cv, new FrameLayout.LayoutParams(
diff --git a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellShellManagementTest.java b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellShellManagementTest.java index 37419f5..a278eafc 100644 --- a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellShellManagementTest.java +++ b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellShellManagementTest.java
@@ -40,14 +40,20 @@ final ContentShellActivity activity = mActivityTestRule.launchContentShellWithUrl(TEST_PAGE_1); Assert.assertEquals(TEST_PAGE_1, - activity.getActiveShell().getContentViewCore().getWebContents().getUrl()); + activity.getActiveShell() + .getContentViewCore() + .getWebContents() + .getVisibleUrl()); Shell previousActiveShell = activity.getActiveShell(); Assert.assertFalse(previousActiveShell.isDestroyed()); mActivityTestRule.loadNewShell(TEST_PAGE_2); Assert.assertEquals(TEST_PAGE_2, - activity.getActiveShell().getContentViewCore().getWebContents().getUrl()); + activity.getActiveShell() + .getContentViewCore() + .getWebContents() + .getVisibleUrl()); Assert.assertNotSame(previousActiveShell, activity.getActiveShell()); Assert.assertTrue(previousActiveShell.isDestroyed());
diff --git a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestCommon.java b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestCommon.java index bda9840..ac347249 100644 --- a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestCommon.java +++ b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestCommon.java
@@ -85,7 +85,8 @@ ContentShellActivity activity = launchContentShellWithUrl(isolatedTestFileUrl); Assert.assertNotNull(mCallback.getActivityForTestCommon()); waitForActiveShellToBeDoneLoading(); - Assert.assertEquals(isolatedTestFileUrl, getContentViewCore().getWebContents().getUrl()); + Assert.assertEquals( + isolatedTestFileUrl, getContentViewCore().getWebContents().getLastCommittedUrl()); return activity; } @@ -107,7 +108,8 @@ updateFailureReason("Shell is still loading."); return false; } - if (TextUtils.isEmpty(shell.getContentViewCore().getWebContents().getUrl())) { + if (TextUtils.isEmpty( + shell.getContentViewCore().getWebContents().getLastCommittedUrl())) { updateFailureReason("Shell's URL is empty or null."); return false; }
diff --git a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellUrlTest.java b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellUrlTest.java index 59ef4cd..ea35aa9 100644 --- a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellUrlTest.java +++ b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellUrlTest.java
@@ -35,7 +35,10 @@ Assert.assertNotNull(activity); // Make sure that the URL is set as expected. - Assert.assertEquals( - URL, activity.getActiveShell().getContentViewCore().getWebContents().getUrl()); + Assert.assertEquals(URL, + activity.getActiveShell() + .getContentViewCore() + .getWebContents() + .getVisibleUrl()); } }
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java index d7a2eb5..6d20e412 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -146,7 +146,8 @@ super.onSaveInstanceState(outState); ContentViewCore contentViewCore = getActiveContentViewCore(); if (contentViewCore != null) { - outState.putString(ACTIVE_SHELL_URL_KEY, contentViewCore.getWebContents().getUrl()); + outState.putString( + ACTIVE_SHELL_URL_KEY, contentViewCore.getWebContents().getLastCommittedUrl()); } mWindowAndroid.saveInstanceState(outState);
diff --git a/content/test/data/accessibility/aria/aria-multiline-expected-blink.txt b/content/test/data/accessibility/aria/aria-multiline-expected-blink.txt new file mode 100644 index 0000000..37f1547 --- /dev/null +++ b/content/test/data/accessibility/aria/aria-multiline-expected-blink.txt
@@ -0,0 +1,3 @@ +rootWebArea +++textField +++textField multiline
diff --git a/content/test/data/accessibility/aria/aria-multiline-expected-win.txt b/content/test/data/accessibility/aria/aria-multiline-expected-win.txt index a34a7163..8fac0ab 100644 --- a/content/test/data/accessibility/aria/aria-multiline-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-multiline-expected-win.txt
@@ -1,3 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++ROLE_SYSTEM_TEXT READONLY IA2_STATE_SINGLE_LINE xml-roles:textbox -++ROLE_SYSTEM_TEXT READONLY IA2_STATE_MULTI_LINE xml-roles:textbox +++ROLE_SYSTEM_TEXT READONLY IA2_STATE_MULTI_LINE xml-roles:textbox \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-multiline.html b/content/test/data/accessibility/aria/aria-multiline.html index e8186a9..3eb9657 100644 --- a/content/test/data/accessibility/aria/aria-multiline.html +++ b/content/test/data/accessibility/aria/aria-multiline.html
@@ -3,6 +3,7 @@ @WIN-ALLOW:IA2_STATE_SINGLE_LINE @WIN-ALLOW:IA2_STATE_MULTI_LINE @WIN-ALLOW:xml-roles* +@BLINK-ALLOW:multiline --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/aria/aria-posinset-expected-blink.txt b/content/test/data/accessibility/aria/aria-posinset-expected-blink.txt index d54814e..b96496d 100644 --- a/content/test/data/accessibility/aria/aria-posinset-expected-blink.txt +++ b/content/test/data/accessibility/aria/aria-posinset-expected-blink.txt
@@ -6,20 +6,20 @@ ++++listBoxOption selectable name='Item 1' setSize=2 posInSet=1 ++++listBoxOption selectable name='Item 2' setSize=2 posInSet=2 ++form -++++radioButton setSize=4 posInSet=3 checkedState=3 +++++radioButton setSize=4 posInSet=3 checkedState=1 ++++staticText name='1' ++++++inlineTextBox name='1' ++++lineBreak name='<newline>' ++++++inlineTextBox name='<newline>' -++++radioButton setSize=4 posInSet=4 checkedState=3 +++++radioButton setSize=4 posInSet=4 checkedState=1 ++++staticText name='2' ++++++inlineTextBox name='2' -++radioButton setSize=2 posInSet=1 checkedState=3 +++radioButton setSize=2 posInSet=1 checkedState=1 ++staticText name='Apple' ++++inlineTextBox name='Apple' ++lineBreak name='<newline>' ++++inlineTextBox name='<newline>' -++radioButton setSize=2 posInSet=2 checkedState=3 +++radioButton setSize=2 posInSet=2 checkedState=1 ++staticText name='Banana' ++++inlineTextBox name='Banana' ++group name='Cake' @@ -38,6 +38,6 @@ ++++++++++inlineTextBox name='red' ++++++lineBreak name='<newline>' ++++++++inlineTextBox name='<newline>' -++++++radioButton name='blue' setSize=1 posInSet=1 checkedState=3 +++++++radioButton name='blue' setSize=1 posInSet=1 checkedState=1 ++staticText name='Done' ++++inlineTextBox name='Done'
diff --git a/content/test/data/accessibility/aria/aria-posinset-expected-mac.txt b/content/test/data/accessibility/aria/aria-posinset-expected-mac.txt index 34903d46..0027c71 100644 --- a/content/test/data/accessibility/aria/aria-posinset-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-posinset-expected-mac.txt
@@ -6,15 +6,15 @@ ++++AXStaticText AXRoleDescription='text' AXValue='Item 1' AXARIASetSize='2' AXARIAPosInSet='1' ++++AXStaticText AXRoleDescription='text' AXValue='Item 2' AXARIASetSize='2' AXARIAPosInSet='2' ++AXGroup AXRoleDescription='form' -++++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='4' AXARIAPosInSet='3' +++++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='4' AXARIAPosInSet='3' ++++AXStaticText AXRoleDescription='text' AXValue='1' ++++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>' -++++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='4' AXARIAPosInSet='4' +++++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='4' AXARIAPosInSet='4' ++++AXStaticText AXRoleDescription='text' AXValue='2' -++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='2' AXARIAPosInSet='1' +++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='2' AXARIAPosInSet='1' ++AXStaticText AXRoleDescription='text' AXValue='Apple' ++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>' -++AXRadioButton AXRoleDescription='radio button' AXValue='2' AXARIASetSize='2' AXARIAPosInSet='2' +++AXRadioButton AXRoleDescription='radio button' AXValue='0' AXARIASetSize='2' AXARIAPosInSet='2' ++AXStaticText AXRoleDescription='text' AXValue='Banana' ++AXGroup AXRoleDescription='group' AXTitle='Cake' ++++AXGroup AXRoleDescription='group' @@ -28,5 +28,5 @@ ++++++AXGroup AXRoleDescription='group' ++++++++AXStaticText AXRoleDescription='text' AXValue='red' ++++++AXUnknown AXRoleDescription='unknown' AXTitle='<newline>' -++++++AXRadioButton AXRoleDescription='radio button' AXTitle='blue' AXValue='2' AXARIASetSize='1' AXARIAPosInSet='1' +++++++AXRadioButton AXRoleDescription='radio button' AXTitle='blue' AXValue='0' AXARIASetSize='1' AXARIAPosInSet='1' ++AXStaticText AXRoleDescription='text' AXValue='Done'
diff --git a/content/test/data/accessibility/aria/aria-posinset-expected-win.txt b/content/test/data/accessibility/aria/aria-posinset-expected-win.txt index dc89ba5..7d6d3e0 100644 --- a/content/test/data/accessibility/aria/aria-posinset-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-posinset-expected-win.txt
@@ -6,15 +6,15 @@ ++++ROLE_SYSTEM_LISTITEM name='Item 1' FOCUSABLE setsize:2 posinset:1 ++++ROLE_SYSTEM_LISTITEM name='Item 2' FOCUSABLE setsize:2 posinset:2 ++IA2_ROLE_FORM -++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:3 checkable:true +++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:3 checkable:true ++++ROLE_SYSTEM_STATICTEXT name='1' ++++ROLE_SYSTEM_WHITESPACE name='<newline>' -++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:4 checkable:true +++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:4 posinset:4 checkable:true ++++ROLE_SYSTEM_STATICTEXT name='2' -++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:1 checkable:true +++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:1 checkable:true ++ROLE_SYSTEM_STATICTEXT name='Apple' ++ROLE_SYSTEM_WHITESPACE name='<newline>' -++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:2 checkable:true +++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE setsize:2 posinset:2 checkable:true ++ROLE_SYSTEM_STATICTEXT name='Banana' ++ROLE_SYSTEM_GROUPING name='Cake' ++++IA2_ROLE_LABEL @@ -28,5 +28,5 @@ ++++++IA2_ROLE_LABEL ++++++++ROLE_SYSTEM_STATICTEXT name='red' ++++++ROLE_SYSTEM_WHITESPACE name='<newline>' -++++++ROLE_SYSTEM_RADIOBUTTON name='blue' MIXED FOCUSABLE IA2_STATE_CHECKABLE setsize:1 posinset:1 checkable:true +++++++ROLE_SYSTEM_RADIOBUTTON name='blue' FOCUSABLE IA2_STATE_CHECKABLE setsize:1 posinset:1 checkable:true ++ROLE_SYSTEM_STATICTEXT name='Done' \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-textbox-expected-blink.txt b/content/test/data/accessibility/aria/aria-textbox-expected-blink.txt index ea8d527..e50c5949 100644 --- a/content/test/data/accessibility/aria/aria-textbox-expected-blink.txt +++ b/content/test/data/accessibility/aria/aria-textbox-expected-blink.txt
@@ -2,6 +2,6 @@ ++textField ++++staticText name='TextBox1' ++++++inlineTextBox name='TextBox1' -++textField +++textField multiline ++++staticText name='TextBox2' -++++++inlineTextBox name='TextBox2' \ No newline at end of file +++++++inlineTextBox name='TextBox2'
diff --git a/content/test/data/accessibility/aria/aria-textbox-expected-win.txt b/content/test/data/accessibility/aria/aria-textbox-expected-win.txt index a7238bc..c38d268 100644 --- a/content/test/data/accessibility/aria/aria-textbox-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-textbox-expected-win.txt
@@ -2,4 +2,4 @@ ++ROLE_SYSTEM_TEXT value='TextBox1' READONLY IA2_STATE_SINGLE_LINE xml-roles:textbox ia2_hypertext='TextBox1' n_selections=0 ++++ROLE_SYSTEM_STATICTEXT name='TextBox1' ia2_hypertext='TextBox1' n_selections=0 ++ROLE_SYSTEM_TEXT value='TextBox2' READONLY IA2_STATE_MULTI_LINE xml-roles:textbox ia2_hypertext='TextBox2' n_selections=0 -++++ROLE_SYSTEM_STATICTEXT name='TextBox2' ia2_hypertext='TextBox2' n_selections=0 +++++ROLE_SYSTEM_STATICTEXT name='TextBox2' ia2_hypertext='TextBox2' n_selections=0 \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-rich-text-expected-win.txt b/content/test/data/accessibility/aria/aria-textbox-with-rich-text-expected-win.txt index e47278b5..0f5ac10 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-rich-text-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-rich-text-expected-win.txt
@@ -1,5 +1,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1>' caret_offset=0 n_selections=0 -++ROLE_SYSTEM_TEXT value='TextBox1<newline><newline>' FOCUSABLE IA2_STATE_MULTI_LINE xml-roles:textbox ia2_hypertext='<obj0>' caret_offset=0 n_selections=0 +++ROLE_SYSTEM_TEXT value='TextBox1<newline><newline>' FOCUSABLE IA2_STATE_SINGLE_LINE xml-roles:textbox ia2_hypertext='<obj0>' caret_offset=0 n_selections=0 ++++IA2_ROLE_HEADING name='TextBox1' xml-roles:heading ia2_hypertext='TextBox1' caret_offset=0 n_selections=0 ++++++ROLE_SYSTEM_STATICTEXT name='TextBox1' ia2_hypertext='TextBox1' caret_offset=0 n_selections=0 ++ROLE_SYSTEM_TEXT value='TextBox2<newline><newline>Some text.' FOCUSABLE IA2_STATE_MULTI_LINE xml-roles:textbox ia2_hypertext='<obj0><obj1>' n_selections=0
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-android.txt b/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-android.txt index f314ee1..61d5a59 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-android.txt
@@ -1,3 +1,3 @@ android.webkit.WebView focusable focused scrollable ++android.widget.EditText clickable editable_text has_non_empty_value name='Single line.' text_change_added_count=12 -++android.widget.EditText clickable editable_text has_non_empty_value multiline name='Multiple<newline>lines.' text_change_added_count=15 \ No newline at end of file +++android.widget.EditText clickable editable_text has_non_empty_value multiline name='Multiple<newline>lines.' text_change_added_count=15
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-blink.txt b/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-blink.txt index 5eccce2..332bf686 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-blink.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-selection-expected-blink.txt
@@ -2,7 +2,7 @@ ++textField ++++staticText name='Single line.' ++++++inlineTextBox name='Single line.' -++textField +++textField multiline ++++staticText name='Multiple' ++++++inlineTextBox name='Multiple' ++++lineBreak name='<newline>'
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-selection.html b/content/test/data/accessibility/aria/aria-textbox-with-selection.html index 8333775..ebe738c 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-selection.html +++ b/content/test/data/accessibility/aria/aria-textbox-with-selection.html
@@ -13,6 +13,7 @@ <html> <body> <div id="text1" role="textbox">Single line.</div> + <!-- Will not expose multiline state because it's not actually editable. --> <div id="text2" role="textbox" aria-multiline="true">Multiple<br>lines.</div> <script>
diff --git a/content/test/data/accessibility/aria/aria-textbox.html b/content/test/data/accessibility/aria/aria-textbox.html index 93435e6..8a0cb02a 100644 --- a/content/test/data/accessibility/aria/aria-textbox.html +++ b/content/test/data/accessibility/aria/aria-textbox.html
@@ -16,6 +16,8 @@ <body> <!-- There should be no selection on the document because the textboxes are not content editable. --> + <!-- There should be no single/multi-line state on the textboxes because + they are not content editable --> <div role="textbox">TextBox1</div> <div role="textbox" aria-multiline="true">TextBox2</div> </body>
diff --git a/content/test/data/accessibility/css/color-expected-blink.txt b/content/test/data/accessibility/css/color-expected-blink.txt index 11c08de6e..2d89989 100644 --- a/content/test/data/accessibility/css/color-expected-blink.txt +++ b/content/test/data/accessibility/css/color-expected-blink.txt
@@ -2,7 +2,7 @@ ++paragraph backgroundColor=-16776961 color=-65536 ++++staticText name='Red on blue.' backgroundColor=-16776961 color=-65536 ++++++inlineTextBox name='Red on blue.' color=-16777216 -++genericContainer backgroundColor=-1 color=-16777216 +++genericContainer multiline backgroundColor=-1 color=-16777216 ++++staticText name='Default.' backgroundColor=-1 color=-16777216 ++++++inlineTextBox name='Default.' color=-16777216 ++++staticText name='Blue background.' backgroundColor=-16776961 color=-16777216
diff --git a/content/test/data/accessibility/css/color-expected-win.txt b/content/test/data/accessibility/css/color-expected-win.txt index 45a1594..31090193 100644 --- a/content/test/data/accessibility/css/color-expected-win.txt +++ b/content/test/data/accessibility/css/color-expected-win.txt
@@ -1,7 +1,7 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE offset:0 background-color:rgb(0\,0\,255) color:rgb(255\,0\,0) offset:1 background-color:rgb(255\,255\,255) color:rgb(0\,0\,0) ia2_hypertext='<obj0><obj1>' ++IA2_ROLE_PARAGRAPH offset:0 background-color:rgb(0\,0\,255) color:rgb(255\,0\,0) ia2_hypertext='Red on blue.' ++++ROLE_SYSTEM_STATICTEXT name='Red on blue.' offset:0 background-color:rgb(0\,0\,255) color:rgb(255\,0\,0) ia2_hypertext='Red on blue.' -++IA2_ROLE_SECTION FOCUSABLE offset:0 background-color:rgb(255\,255\,255) color:rgb(0\,0\,0) offset:8 background-color:rgb(0\,0\,255) color:rgb(0\,0\,0) offset:24 background-color:rgb(255\,255\,255) color:rgb(0\,255\,0) ia2_hypertext='Default.Blue background.Green text.' +++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_MULTI_LINE offset:0 background-color:rgb(255\,255\,255) color:rgb(0\,0\,0) offset:8 background-color:rgb(0\,0\,255) color:rgb(0\,0\,0) offset:24 background-color:rgb(255\,255\,255) color:rgb(0\,255\,0) ia2_hypertext='Default.Blue background.Green text.' ++++ROLE_SYSTEM_STATICTEXT name='Default.' offset:0 background-color:rgb(255\,255\,255) color:rgb(0\,0\,0) ia2_hypertext='Default.' ++++ROLE_SYSTEM_STATICTEXT name='Blue background.' offset:0 background-color:rgb(0\,0\,255) color:rgb(0\,0\,0) ia2_hypertext='Blue background.' -++++ROLE_SYSTEM_STATICTEXT name='Green text.' offset:0 background-color:rgb(255\,255\,255) color:rgb(0\,255\,0) ia2_hypertext='Green text.' +++++ROLE_SYSTEM_STATICTEXT name='Green text.' offset:0 background-color:rgb(255\,255\,255) color:rgb(0\,255\,0) ia2_hypertext='Green text.' \ No newline at end of file
diff --git a/content/test/data/accessibility/css/font-style-expected-blink.txt b/content/test/data/accessibility/css/font-style-expected-blink.txt index 4866fe8e..846a3be5 100644 --- a/content/test/data/accessibility/css/font-style-expected-blink.txt +++ b/content/test/data/accessibility/css/font-style-expected-blink.txt
@@ -14,7 +14,7 @@ ++++++inlineTextBox name='over' ++++staticText name='dog' textStyle=7 ++++++inlineTextBox name='dog' -++genericContainer +++genericContainer multiline ++++staticText name='Normal' ++++++inlineTextBox name='Normal' ++++staticText name='bold' textStyle=1
diff --git a/content/test/data/accessibility/css/font-style-expected-win.txt b/content/test/data/accessibility/css/font-style-expected-win.txt index ce99610..91f4de0 100644 --- a/content/test/data/accessibility/css/font-style-expected-win.txt +++ b/content/test/data/accessibility/css/font-style-expected-win.txt
@@ -7,9 +7,9 @@ ++++ROLE_SYSTEM_STATICTEXT name='jumped' offset:0 font-style:italic font-weight:bold text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none ia2_hypertext='jumped' ++++ROLE_SYSTEM_STATICTEXT name='over' offset:0 font-style:italic font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:solid text-underline-type:single ia2_hypertext='over' ++++ROLE_SYSTEM_STATICTEXT name='dog' offset:0 font-style:italic font-weight:bold text-line-through-style:none text-line-through-type:none text-underline-style:solid text-underline-type:single ia2_hypertext='dog' -++IA2_ROLE_SECTION FOCUSABLE offset:0 font-style:normal font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none offset:6 font-style:normal font-weight:bold text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none offset:10 font-style:italic font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none offset:16 font-style:normal font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:solid text-underline-type:single offset:25 font-style:normal font-weight:normal text-line-through-style:solid text-line-through-type:single text-underline-style:none text-underline-type:none ia2_hypertext='Normalbolditalicunderlineline-through' +++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_MULTI_LINE offset:0 font-style:normal font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none offset:6 font-style:normal font-weight:bold text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none offset:10 font-style:italic font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none offset:16 font-style:normal font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:solid text-underline-type:single offset:25 font-style:normal font-weight:normal text-line-through-style:solid text-line-through-type:single text-underline-style:none text-underline-type:none ia2_hypertext='Normalbolditalicunderlineline-through' ++++ROLE_SYSTEM_STATICTEXT name='Normal' offset:0 font-style:normal font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none ia2_hypertext='Normal' ++++ROLE_SYSTEM_STATICTEXT name='bold' offset:0 font-style:normal font-weight:bold text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none ia2_hypertext='bold' ++++ROLE_SYSTEM_STATICTEXT name='italic' offset:0 font-style:italic font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:none text-underline-type:none ia2_hypertext='italic' ++++ROLE_SYSTEM_STATICTEXT name='underline' offset:0 font-style:normal font-weight:normal text-line-through-style:none text-line-through-type:none text-underline-style:solid text-underline-type:single ia2_hypertext='underline' -++++ROLE_SYSTEM_STATICTEXT name='line-through' offset:0 font-style:normal font-weight:normal text-line-through-style:solid text-line-through-type:single text-underline-style:none text-underline-type:none ia2_hypertext='line-through' +++++ROLE_SYSTEM_STATICTEXT name='line-through' offset:0 font-style:normal font-weight:normal text-line-through-style:solid text-line-through-type:single text-underline-style:none text-underline-type:none ia2_hypertext='line-through' \ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-collapse-expected-win.txt b/content/test/data/accessibility/event/aria-combo-box-collapse-expected-win.txt index 3badd56..15e2fa9 100644 --- a/content/test/data/accessibility/event/aria-combo-box-collapse-expected-win.txt +++ b/content/test/data/accessibility/event/aria-combo-box-collapse-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_STATECHANGE on role=ROLE_SYSTEM_COMBOBOX FOCUSED,COLLAPSED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_COMBOBOX FOCUSED,COLLAPSED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL -IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on role=ROLE_SYSTEM_COMBOBOX FOCUSED,COLLAPSED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL +IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on role=ROLE_SYSTEM_COMBOBOX FOCUSED,COLLAPSED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL \ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-expand-expected-win.txt b/content/test/data/accessibility/event/aria-combo-box-expand-expected-win.txt index db3df37c..c70c745e4 100644 --- a/content/test/data/accessibility/event/aria-combo-box-expand-expected-win.txt +++ b/content/test/data/accessibility/event/aria-combo-box-expand-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_STATECHANGE on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Apple" FOCUSED,FOCUSABLE,SELECTABLE -IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL +IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL \ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-focus-expected-win.txt b/content/test/data/accessibility/event/aria-combo-box-focus-expected-win.txt index 6b53ceb..f0b6aea 100644 --- a/content/test/data/accessibility/event/aria-combo-box-focus-expected-win.txt +++ b/content/test/data/accessibility/event/aria-combo-box-focus-expected-win.txt
@@ -1,2 +1,2 @@ EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Apple" FOCUSED,FOCUSABLE,SELECTABLE -IA2_EVENT_TEXT_CARET_MOVED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL +IA2_EVENT_TEXT_CARET_MOVED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL \ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-next-expected-win.txt b/content/test/data/accessibility/event/aria-combo-box-next-expected-win.txt index c68d47f0..71d5544 100644 --- a/content/test/data/accessibility/event/aria-combo-box-next-expected-win.txt +++ b/content/test/data/accessibility/event/aria-combo-box-next-expected-win.txt
@@ -1,2 +1,2 @@ EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Banana" FOCUSED,FOCUSABLE,SELECTABLE -IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL +IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on role=ROLE_SYSTEM_COMBOBOX EXPANDED,FOCUSABLE,HASPOPUP IA2_STATE_EDITABLE,IA2_STATE_SUPPORTS_AUTOCOMPLETION,IA2_STATE_VERTICAL \ No newline at end of file
diff --git a/content/test/data/accessibility/html/action-verbs-expected-blink.txt b/content/test/data/accessibility/html/action-verbs-expected-blink.txt index 814f2e5..b886a2b 100644 --- a/content/test/data/accessibility/html/action-verbs-expected-blink.txt +++ b/content/test/data/accessibility/html/action-verbs-expected-blink.txt
@@ -12,7 +12,7 @@ ++textField ++checkBox defaultActionVerb=2 checkedState=1 ++checkBox defaultActionVerb=8 checkedState=2 -++radioButton defaultActionVerb=7 checkedState=3 +++radioButton defaultActionVerb=7 checkedState=1 ++switch name='ARIA Switch' defaultActionVerb=2 checkedState=1 ++popUpButton collapsed haspopup defaultActionVerb=5 ++++menuListPopup invisible activedescendantId=menuListOption
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt index f38d219a..6ac67df 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-blink.txt
@@ -1,10 +1,10 @@ rootWebArea -++genericContainer editable richlyEditable +++genericContainer editable multiline richlyEditable ++++paragraph editable richlyEditable ++++++staticText editable richlyEditable name='A contenteditable with a ' ++++++++inlineTextBox name='A contenteditable with a ' -++++++link editable richlyEditable name='link' -++++++++staticText editable richlyEditable name='link' +++++++link editable linked richlyEditable name='link' +++++++++staticText editable linked richlyEditable name='link' ++++++++++inlineTextBox name='link' ++++++staticText editable richlyEditable name=' and an ' ++++++++inlineTextBox name=' and an ' @@ -29,6 +29,6 @@ ++paragraph ++++staticText name='Non-editable paragraph.' ++++++inlineTextBox name='Non-editable paragraph.' -++paragraph editable richlyEditable +++paragraph editable multiline richlyEditable ++++staticText editable richlyEditable name='Should keep the role but change the state.' -++++++inlineTextBox name='Should keep the role but change the state.' \ No newline at end of file +++++++inlineTextBox name='Should keep the role but change the state.'
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt index 35b988c..86f8dd9 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt
@@ -1,5 +1,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1><obj2>' n_selections=0 -++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE ia2_hypertext='<obj0><obj1><obj2>' n_selections=0 +++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE ia2_hypertext='<obj0><obj1><obj2>' n_selections=0 ++++IA2_ROLE_PARAGRAPH IA2_STATE_EDITABLE ia2_hypertext='A contenteditable with a <obj1> and an <obj3> and a <obj5>.' n_selections=0 ++++++ROLE_SYSTEM_STATICTEXT name='A contenteditable with a ' IA2_STATE_EDITABLE ia2_hypertext='A contenteditable with a ' n_selections=0 ++++++ROLE_SYSTEM_LINK name='link' LINKED IA2_STATE_EDITABLE ia2_hypertext='link' n_selections=0 @@ -21,5 +21,5 @@ ++++++++ROLE_SYSTEM_STATICTEXT name='Editable list item.' IA2_STATE_EDITABLE ia2_hypertext='Editable list item.' n_selections=0 ++IA2_ROLE_PARAGRAPH ia2_hypertext='Non-editable paragraph.' n_selections=0 ++++ROLE_SYSTEM_STATICTEXT name='Non-editable paragraph.' ia2_hypertext='Non-editable paragraph.' n_selections=0 -++IA2_ROLE_PARAGRAPH FOCUSABLE IA2_STATE_EDITABLE ia2_hypertext='Should keep the role but change the state.' n_selections=0 +++IA2_ROLE_PARAGRAPH FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE ia2_hypertext='Should keep the role but change the state.' n_selections=0 ++++ROLE_SYSTEM_STATICTEXT name='Should keep the role but change the state.' IA2_STATE_EDITABLE ia2_hypertext='Should keep the role but change the state.' n_selections=0
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt index ea1a5dc..83490c7f 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-blink.txt
@@ -1,5 +1,5 @@ rootWebArea -++genericContainer editable richlyEditable +++genericContainer editable multiline richlyEditable ++++paragraph editable richlyEditable ++++++staticText editable richlyEditable name='A contenteditable with a ' TreeData.textSelStartOffset=0 ++++++++inlineTextBox name='A contenteditable with a '
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-win.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-win.txt index 82914951..badd9296 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-win.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-win.txt
@@ -1,5 +1,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>' caret_offset=1 n_selections=1 selection_start=0 selection_end=1 -++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE ia2_hypertext='<obj0><obj1><obj2>' caret_offset=3 n_selections=1 selection_start=0 selection_end=3 +++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE ia2_hypertext='<obj0><obj1><obj2>' caret_offset=3 n_selections=1 selection_start=0 selection_end=3 ++++IA2_ROLE_PARAGRAPH IA2_STATE_EDITABLE ia2_hypertext='A contenteditable with a <obj1> and an <obj3> and a <obj5>.' n_selections=1 selection_start=0 selection_end=44 ++++++ROLE_SYSTEM_STATICTEXT name='A contenteditable with a ' IA2_STATE_EDITABLE ia2_hypertext='A contenteditable with a ' n_selections=1 selection_start=0 selection_end=25 ++++++ROLE_SYSTEM_LINK name='link' LINKED IA2_STATE_EDITABLE ia2_hypertext='link' n_selections=1 selection_start=0 selection_end=4
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html b/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html index 7249361..ee1d1931 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html +++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html
@@ -1,5 +1,7 @@ <!-- @WIN-ALLOW:IA2_STATE_EDITABLE +@WIN-ALLOW:IA2_STATE_MULTI_LINE +@WIN-ALLOW:IA2_STATE_SINGLE_LINE @WIN-ALLOW:LINKED @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:caret_offset*
diff --git a/content/test/data/accessibility/html/contenteditable-descendants.html b/content/test/data/accessibility/html/contenteditable-descendants.html index 2b678a3..822e778d 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants.html +++ b/content/test/data/accessibility/html/contenteditable-descendants.html
@@ -1,11 +1,14 @@ <!-- @WIN-ALLOW:caret_offset* @WIN-ALLOW:IA2_STATE_EDITABLE +@WIN-ALLOW:IA2_STATE_MULTI_LINE @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:LINKED @WIN-ALLOW:n_selections* @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* +@WIN-DENY:value +@BLINK-ALLOW:linked @BLINK-ALLOW:editable* @BLINK-ALLOW:richlyEditable* @BLINK-ALLOW:textSel*
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt index 2d02822..521e850 100644 --- a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-blink.txt
@@ -1,5 +1,5 @@ rootWebArea -++genericContainer editable richlyEditable +++genericContainer editable multiline richlyEditable ++++paragraph editable richlyEditable ++++++staticText editable richlyEditable name='This is editable.' ++++++++inlineTextBox name='This is editable.' @@ -7,9 +7,9 @@ ++++++inlineTextBox name='This is not editable.' ++++lineBreak name='<newline>' ++++++inlineTextBox name='<newline>' -++++paragraph editable richlyEditable +++++paragraph editable multiline richlyEditable ++++++staticText editable richlyEditable name='But this one is.' ++++++++inlineTextBox name='But this one is.' -++++paragraph editable richlyEditable +++++paragraph editable multiline richlyEditable ++++++staticText editable richlyEditable name='So is this one.' ++++++++inlineTextBox name='So is this one.' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-win.txt b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-win.txt index 7d8750a..f6bf3ab 100644 --- a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-win.txt +++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-win.txt
@@ -1,5 +1,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>' n_selections=0 -++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE ia2_hypertext='<obj0>This is not editable.<newline><obj3><obj4>' n_selections=0 +++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE ia2_hypertext='<obj0>This is not editable.<newline><obj3><obj4>' n_selections=0 ++++IA2_ROLE_PARAGRAPH IA2_STATE_EDITABLE ia2_hypertext='This is editable.' n_selections=0 ++++++ROLE_SYSTEM_STATICTEXT name='This is editable.' IA2_STATE_EDITABLE ia2_hypertext='This is editable.' n_selections=0 ++++ROLE_SYSTEM_STATICTEXT name='This is not editable.' ia2_hypertext='This is not editable.' n_selections=0
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-blink.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-blink.txt index 81fbe1da..84d0ae9 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-blink.txt +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-blink.txt
@@ -1,7 +1,7 @@ rootWebArea -++genericContainer editable richlyEditable name='label' -++genericContainer editable richlyEditable description='description' descriptionFrom=5 -++genericContainer editable richlyEditable name='title' +++genericContainer editable multiline richlyEditable name='label' +++genericContainer editable multiline richlyEditable description='description' descriptionFrom=5 +++genericContainer editable multiline richlyEditable name='title' ++paragraph ++++staticText name='description' ++++++inlineTextBox name='description'
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-win.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-win.txt index bd199c7..2097684 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-win.txt +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-win.txt
@@ -1,6 +1,6 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1><obj2><obj3>' -++IA2_ROLE_SECTION name='label' FOCUSABLE IA2_STATE_EDITABLE -++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE description='description' -++IA2_ROLE_SECTION name='title' FOCUSABLE IA2_STATE_EDITABLE +++IA2_ROLE_SECTION name='label' FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE +++IA2_ROLE_SECTION FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE description='description' +++IA2_ROLE_SECTION name='title' FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE ++IA2_ROLE_PARAGRAPH ia2_hypertext='description' -++++ROLE_SYSTEM_STATICTEXT name='description' ia2_hypertext='description' +++++ROLE_SYSTEM_STATICTEXT name='description' ia2_hypertext='description' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-radio-expected-blink.txt b/content/test/data/accessibility/html/input-radio-expected-blink.txt index da8eeddd..0c3f3edd 100644 --- a/content/test/data/accessibility/html/input-radio-expected-blink.txt +++ b/content/test/data/accessibility/html/input-radio-expected-blink.txt
@@ -1,16 +1,16 @@ rootWebArea ++form -++++radioButton checkedState=3 radioGroupIds=radioButton +++++radioButton checkedState=1 radioGroupIds=radioButton ++++staticText name='Radio1' ++++++inlineTextBox name='Radio1' ++++lineBreak name='<newline>' ++++++inlineTextBox name='<newline>' -++++radioButton checkedState=3 radioGroupIds=radioButton +++++radioButton checkedState=1 radioGroupIds=radioButton ++++staticText name='Radio2' ++++++inlineTextBox name='Radio2' ++form ++++radioButton name='Radio3' checkedState=1 radioGroupIds=radioButton,radioButton ++++radioButton name='Radio4' checkedState=2 radioGroupIds=radioButton,radioButton ++form -++++radioButton name='Radio5' checkedState=3 radioGroupIds=radioButton +++++radioButton name='Radio5' checkedState=1 radioGroupIds=radioButton ++++radioButton name='Radio6' checkedState=2 radioGroupIds=radioButton \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-radio-expected-mac.txt b/content/test/data/accessibility/html/input-radio-expected-mac.txt index c54984b..52457e38 100644 --- a/content/test/data/accessibility/html/input-radio-expected-mac.txt +++ b/content/test/data/accessibility/html/input-radio-expected-mac.txt
@@ -1,13 +1,13 @@ AXWebArea ++AXGroup -++++AXRadioButton AXValue='2' AXLinkedUIElements=["AXRadioButton 2"] +++++AXRadioButton AXValue='0' AXLinkedUIElements=["AXRadioButton 0"] ++++AXStaticText AXValue='Radio1' ++++AXUnknown AXTitle='<newline>' -++++AXRadioButton AXValue='2' AXLinkedUIElements=["AXRadioButton 2"] +++++AXRadioButton AXValue='0' AXLinkedUIElements=["AXRadioButton 0"] ++++AXStaticText AXValue='Radio2' ++AXGroup ++++AXRadioButton AXTitle='Radio3' AXValue='0' AXLinkedUIElements=["AXRadioButton Radio3","AXRadioButton Radio4"] ++++AXRadioButton AXTitle='Radio4' AXValue='1' AXLinkedUIElements=["AXRadioButton Radio3","AXRadioButton Radio4"] ++AXGroup -++++AXRadioButton AXTitle='Radio5' AXValue='2' AXLinkedUIElements=["AXRadioButton Radio5"] +++++AXRadioButton AXTitle='Radio5' AXValue='0' AXLinkedUIElements=["AXRadioButton Radio5"] ++++AXRadioButton AXTitle='Radio6' AXValue='1' AXLinkedUIElements=["AXRadioButton Radio6"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-radio-expected-win.txt b/content/test/data/accessibility/html/input-radio-expected-win.txt index 188dcd9..6e763ba 100644 --- a/content/test/data/accessibility/html/input-radio-expected-win.txt +++ b/content/test/data/accessibility/html/input-radio-expected-win.txt
@@ -1,13 +1,13 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1><obj2>' ++IA2_ROLE_FORM ia2_hypertext='<obj0>Radio1<newline><obj3>Radio2' -++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE checkable:true +++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE checkable:true ++++ROLE_SYSTEM_STATICTEXT name='Radio1' ia2_hypertext='Radio1' ++++ROLE_SYSTEM_WHITESPACE name='<newline>' ia2_hypertext='<newline>' -++++ROLE_SYSTEM_RADIOBUTTON MIXED FOCUSABLE IA2_STATE_CHECKABLE checkable:true +++++ROLE_SYSTEM_RADIOBUTTON FOCUSABLE IA2_STATE_CHECKABLE checkable:true ++++ROLE_SYSTEM_STATICTEXT name='Radio2' ia2_hypertext='Radio2' ++IA2_ROLE_FORM ia2_hypertext='<obj0><obj1>' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio3' FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio3' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio4' CHECKED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio4' ++IA2_ROLE_FORM ia2_hypertext='<obj0><obj1>' -++++ROLE_SYSTEM_RADIOBUTTON name='Radio5' MIXED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio5' +++++ROLE_SYSTEM_RADIOBUTTON name='Radio5' FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio5' ++++ROLE_SYSTEM_RADIOBUTTON name='Radio6' CHECKED FOCUSABLE IA2_STATE_CHECKABLE checkable:true ia2_hypertext='Radio6'
diff --git a/content/test/data/accessibility/html/input-text-value-expected-blink.txt b/content/test/data/accessibility/html/input-text-value-expected-blink.txt index c76afc11..669039a 100644 --- a/content/test/data/accessibility/html/input-text-value-expected-blink.txt +++ b/content/test/data/accessibility/html/input-text-value-expected-blink.txt
@@ -1,18 +1,18 @@ -rootWebArea +rootWebArea focusable ++genericContainer ++++labelText ++++++staticText name='l1' ++++++++inlineTextBox name='l1' -++++textField name='l1' +++++textField focusable name='l1' ++++labelText ++++++staticText name='l2' ++++++++inlineTextBox name='l2' -++++textField name='l2' +++++textField focusable name='l2' ++++++genericContainer ++++++++staticText name='value' ++++++++++inlineTextBox name='value' -++++textField name='l2' -++++textField name='l2' +++++textField focusable name='l2' +++++textField focusable name='l2' ++++++genericContainer ++++++++staticText name='value' ++++++++++inlineTextBox name='value' @@ -20,13 +20,13 @@ ++++++staticText name='Email' ++++++++inlineTextBox name='Email' ++++genericContainer -++++textField name='Email' -++++textField name='Email' +++++textField focusable name='Email' +++++textField focusable name='Email' ++++++genericContainer ++++++++staticText name='value' ++++++++++inlineTextBox name='value' -++++textField name='l5' -++++textField name='l6' +++++textField focusable multiline name='l5' +++++textField focusable multiline name='l6' ++++++genericContainer ++++++++staticText name='Value' -++++++++++inlineTextBox name='Value' \ No newline at end of file +++++++++++inlineTextBox name='Value'
diff --git a/content/test/data/accessibility/html/input-text-value-expected-win.txt b/content/test/data/accessibility/html/input-text-value-expected-win.txt new file mode 100644 index 0000000..9341528 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-value-expected-win.txt
@@ -0,0 +1,17 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++IA2_ROLE_SECTION +++++IA2_ROLE_LABEL +++++++ROLE_SYSTEM_STATICTEXT name='l1' +++++ROLE_SYSTEM_TEXT name='l1' FOCUSABLE +++++IA2_ROLE_LABEL +++++++ROLE_SYSTEM_STATICTEXT name='l2' +++++ROLE_SYSTEM_TEXT name='l2' FOCUSABLE +++++ROLE_SYSTEM_TEXT name='l2' FOCUSABLE +++++ROLE_SYSTEM_TEXT name='l2' FOCUSABLE +++++IA2_ROLE_LABEL +++++++ROLE_SYSTEM_STATICTEXT name='Email' +++++IA2_ROLE_SECTION +++++ROLE_SYSTEM_TEXT name='Email' FOCUSABLE +++++ROLE_SYSTEM_TEXT name='Email' FOCUSABLE +++++ROLE_SYSTEM_TEXT name='l5' FOCUSABLE IA2_STATE_MULTI_LINE +++++ROLE_SYSTEM_TEXT name='l6' FOCUSABLE IA2_STATE_MULTI_LINE
diff --git a/content/test/data/accessibility/html/input-text-value.html b/content/test/data/accessibility/html/input-text-value.html index d6f3697b..22814a0 100644 --- a/content/test/data/accessibility/html/input-text-value.html +++ b/content/test/data/accessibility/html/input-text-value.html
@@ -1,5 +1,9 @@ <!-- @WIN-ALLOW:description* +@WIN-ALLOW:IA2_STATE_MULTI_LINE +@BLINK-ALLOW:description* +@BLINK-ALLOW:focus* +@BLINK-ALLOW:multiline --> <html> <body>
diff --git a/content/test/data/accessibility/html/textarea-expected-blink.txt b/content/test/data/accessibility/html/textarea-expected-blink.txt index 909da1525..f479e46f 100644 --- a/content/test/data/accessibility/html/textarea-expected-blink.txt +++ b/content/test/data/accessibility/html/textarea-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea ++genericContainer -++++textField textSelStart=0 textSelEnd=0 +++++textField multiline textSelStart=0 textSelEnd=0 ++++++genericContainer ++++++++staticText name='The textarea tag defines a multi-line text input control.<newline>' ++++++++++inlineTextBox name='The textarea tag defines a multi-line text input'
diff --git a/content/test/data/accessibility/html/textarea-read-only-expected-blink.txt b/content/test/data/accessibility/html/textarea-read-only-expected-blink.txt index b1d7ba46..72ce41e5 100644 --- a/content/test/data/accessibility/html/textarea-read-only-expected-blink.txt +++ b/content/test/data/accessibility/html/textarea-read-only-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea ++genericContainer -++++textField textSelStart=0 textSelEnd=0 +++++textField multiline textSelStart=0 textSelEnd=0 ++++++genericContainer ++++++++staticText name='The textarea tag defines a multi-line text input control.<newline>' ++++++++++inlineTextBox name='The textarea tag defines a multi-line text input'
diff --git a/content/test/data/accessibility/html/textarea-with-selection-expected-blink.txt b/content/test/data/accessibility/html/textarea-with-selection-expected-blink.txt index f12d086..670d10cb 100644 --- a/content/test/data/accessibility/html/textarea-with-selection-expected-blink.txt +++ b/content/test/data/accessibility/html/textarea-with-selection-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea ++genericContainer -++++textField textSelStart=0 textSelEnd=58 +++++textField multiline textSelStart=0 textSelEnd=58 ++++++genericContainer ++++++++staticText name='The textarea tag defines a multi-line text input control.<newline>' ++++++++++inlineTextBox name='The textarea tag defines a multi-line text input'
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 19ec8b91..d78c36a 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -1349,7 +1349,7 @@ 'audio_unittests': { 'tester_configs': [ { - 'predicate': Predicates.FYI_ONLY, + 'predicate': Predicates.FYI_AND_OPTIONAL, } ], # Don't run these tests on Android.
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index de720ae..71239a1d 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface_manager.h" #include "content/browser/compositor/image_transport_factory.h" #include "content/browser/compositor/surface_utils.h" @@ -68,12 +69,12 @@ background_color_(SK_ColorWHITE) { #if defined(OS_ANDROID) frame_sink_id_ = AllocateFrameSinkId(); - GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_); + GetFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_); #else // Not all tests initialize or need an image transport factory. if (ImageTransportFactory::GetInstance()) { frame_sink_id_ = AllocateFrameSinkId(); - GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_); + GetFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_); } #endif @@ -88,7 +89,7 @@ } TestRenderWidgetHostView::~TestRenderWidgetHostView() { - cc::SurfaceManager* manager = GetSurfaceManager(); + cc::FrameSinkManager* manager = GetFrameSinkManager(); if (manager) { manager->InvalidateFrameSinkId(frame_sink_id_); }
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc index ac14a0b8..7369046 100644 --- a/content/test/test_web_contents.cc +++ b/content/test/test_web_contents.cc
@@ -389,10 +389,12 @@ void TestWebContents::CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) {} void TestWebContents::CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) {} + int32_t route_id, + mojom::WidgetPtr widget) {} void TestWebContents::ShowCreatedWindow(int process_id, int route_id,
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h index 2d2844e3..f075d52a 100644 --- a/content/test/test_web_contents.h +++ b/content/test/test_web_contents.h
@@ -159,9 +159,11 @@ SessionStorageNamespace* session_storage_namespace) override; void CreateNewWidget(int32_t render_process_id, int32_t route_id, + mojom::WidgetPtr widget, blink::WebPopupType popup_type) override; void CreateNewFullscreenWidget(int32_t render_process_id, - int32_t route_id) override; + int32_t route_id, + mojom::WidgetPtr widget) override; void ShowCreatedWindow(int process_id, int route_id, WindowOpenDisposition disposition,
diff --git a/device/geolocation/location_arbitrator.h b/device/geolocation/location_arbitrator.h index dca5dbe..343d366 100644 --- a/device/geolocation/location_arbitrator.h +++ b/device/geolocation/location_arbitrator.h
@@ -12,7 +12,6 @@ #include "base/callback_forward.h" #include "base/cancelable_callback.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "device/geolocation/access_token_store.h"
diff --git a/device/usb/mojo/type_converters.cc b/device/usb/mojo/type_converters.cc index fbe17d8..89034c9 100644 --- a/device/usb/mojo/type_converters.cc +++ b/device/usb/mojo/type_converters.cc
@@ -10,8 +10,7 @@ #include <map> #include <utility> -#include "base/logging.h" -#include "base/strings/utf_string_conversions.h" +#include "device/usb/usb_descriptors.h" #include "device/usb/usb_device.h" namespace mojo { @@ -111,9 +110,9 @@ info->device_version_major = device.device_version() >> 8; info->device_version_minor = device.device_version() >> 4 & 0xf; info->device_version_subminor = device.device_version() & 0xf; - info->manufacturer_name = base::UTF16ToUTF8(device.manufacturer_string()); - info->product_name = base::UTF16ToUTF8(device.product_string()); - info->serial_number = base::UTF16ToUTF8(device.serial_number()); + info->manufacturer_name = device.manufacturer_string(); + info->product_name = device.product_string(); + info->serial_number = device.serial_number(); const device::UsbConfigDescriptor* config = device.active_configuration(); info->active_configuration = config ? config->configuration_value : 0; info->configurations =
diff --git a/device/usb/mojo/type_converters.h b/device/usb/mojo/type_converters.h index fc26bb75..afd4188 100644 --- a/device/usb/mojo/type_converters.h +++ b/device/usb/mojo/type_converters.h
@@ -9,7 +9,6 @@ #include "device/usb/public/interfaces/device.mojom.h" #include "device/usb/public/interfaces/device_manager.mojom.h" -#include "device/usb/usb_descriptors.h" #include "device/usb/usb_device_handle.h" #include "mojo/public/cpp/bindings/type_converter.h" @@ -18,7 +17,10 @@ // that uses these conversions explicitly or implicitly. namespace device { +struct UsbConfigDescriptor; class UsbDevice; +struct UsbEndpointDescriptor; +struct UsbInterfaceDescriptor; } namespace mojo {
diff --git a/device/usb/public/cpp/BUILD.gn b/device/usb/public/cpp/BUILD.gn index 717c2a9..c555039 100644 --- a/device/usb/public/cpp/BUILD.gn +++ b/device/usb/public/cpp/BUILD.gn
@@ -9,7 +9,6 @@ ] deps = [ - "//base", "//device/usb", "//device/usb/public/interfaces", ]
diff --git a/device/usb/public/cpp/filter_utils.cc b/device/usb/public/cpp/filter_utils.cc index 021af336..e8ac314 100644 --- a/device/usb/public/cpp/filter_utils.cc +++ b/device/usb/public/cpp/filter_utils.cc
@@ -4,7 +4,6 @@ #include "device/usb/public/cpp/filter_utils.h" -#include "base/strings/utf_string_conversions.h" #include "device/usb/usb_device.h" namespace device { @@ -19,10 +18,8 @@ return false; } - if (filter.serial_number && - device.serial_number() != base::UTF8ToUTF16(*filter.serial_number)) { + if (filter.serial_number && device.serial_number() != *filter.serial_number) return false; - } if (filter.has_class_code) { for (const UsbConfigDescriptor& config : device.configurations()) {
diff --git a/device/usb/public/cpp/filter_utils_unittest.cc b/device/usb/public/cpp/filter_utils_unittest.cc index eeaf007..2cf8f63 100644 --- a/device/usb/public/cpp/filter_utils_unittest.cc +++ b/device/usb/public/cpp/filter_utils_unittest.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <string> #include <vector> #include "base/memory/ref_counted.h" +#include "base/strings/utf_string_conversions.h" #include "device/usb/mock_usb_device.h" #include "device/usb/public/cpp/filter_utils.h" #include "device/usb/usb_descriptors.h" @@ -125,7 +125,7 @@ TEST_F(UsbFilterTest, MatchSerialNumber) { auto filter = mojom::UsbDeviceFilter::New(); - filter->serial_number = std::string("ABC123"); + filter->serial_number = base::ASCIIToUTF16("ABC123"); EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); filter->has_vendor_id = true; filter->vendor_id = 0x18d1; @@ -133,7 +133,7 @@ filter->vendor_id = 0x18d2; EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); filter->vendor_id = 0x18d1; - filter->serial_number = std::string("DIFFERENT"); + filter->serial_number = base::ASCIIToUTF16("DIFFERENT"); EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); }
diff --git a/device/usb/public/interfaces/BUILD.gn b/device/usb/public/interfaces/BUILD.gn index 2ff08c00..ea8c6a5 100644 --- a/device/usb/public/interfaces/BUILD.gn +++ b/device/usb/public/interfaces/BUILD.gn
@@ -11,6 +11,10 @@ "device_manager.mojom", ] + deps = [ + "//mojo/common:common_custom_types", + ] + # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. use_once_callback = false }
diff --git a/device/usb/public/interfaces/device.mojom b/device/usb/public/interfaces/device.mojom index d1c139a..11ded46 100644 --- a/device/usb/public/interfaces/device.mojom +++ b/device/usb/public/interfaces/device.mojom
@@ -4,6 +4,8 @@ module device.mojom; +import "mojo/common/string16.mojom"; + enum UsbOpenDeviceError { // Opening the device succeeded. OK, @@ -55,7 +57,7 @@ uint8 class_code; uint8 subclass_code; uint8 protocol_code; - string? interface_name; + mojo.common.mojom.String16? interface_name; array<UsbEndpointInfo> endpoints; }; @@ -66,7 +68,7 @@ struct UsbConfigurationInfo { uint8 configuration_value; - string? configuration_name; + mojo.common.mojom.String16? configuration_name; array<UsbInterfaceInfo> interfaces; }; @@ -83,9 +85,9 @@ uint8 device_version_major; uint8 device_version_minor; uint8 device_version_subminor; - string? manufacturer_name; - string? product_name; - string? serial_number; + mojo.common.mojom.String16? manufacturer_name; + mojo.common.mojom.String16? product_name; + mojo.common.mojom.String16? serial_number; uint8 active_configuration; array<UsbConfigurationInfo> configurations; };
diff --git a/device/usb/public/interfaces/device_manager.mojom b/device/usb/public/interfaces/device_manager.mojom index 4a4ec723..99853d5d 100644 --- a/device/usb/public/interfaces/device_manager.mojom +++ b/device/usb/public/interfaces/device_manager.mojom
@@ -4,7 +4,8 @@ module device.mojom; -import "device.mojom"; +import "device/usb/public/interfaces/device.mojom"; +import "mojo/common/string16.mojom"; struct UsbDeviceFilter { bool has_vendor_id; @@ -22,7 +23,7 @@ bool has_protocol_code; uint8 protocol_code; - string? serial_number; + mojo.common.mojom.String16? serial_number; }; struct UsbEnumerationOptions {
diff --git a/device/vr/android/gvr/gvr_delegate.h b/device/vr/android/gvr/gvr_delegate.h index d9562c52..fbf6f46 100644 --- a/device/vr/android/gvr/gvr_delegate.h +++ b/device/vr/android/gvr/gvr_delegate.h
@@ -47,8 +47,8 @@ uint32_t device_id); virtual void SetWebVRSecureOrigin(bool secure_origin) = 0; - virtual void UpdateVSyncInterval(int64_t timebase_nanos, - double interval_seconds) = 0; + virtual void UpdateVSyncInterval(base::TimeTicks vsync_timebase, + base::TimeDelta vsync_interval) = 0; virtual void CreateVRDisplayInfo( const base::Callback<void(mojom::VRDisplayInfoPtr)>& callback, uint32_t device_id) = 0;
diff --git a/extensions/browser/extension_util.cc b/extensions/browser/extension_util.cc index 5ed98fc..1863b1c 100644 --- a/extensions/browser/extension_util.cc +++ b/extensions/browser/extension_util.cc
@@ -29,23 +29,6 @@ } // namespace -bool HasIsolatedStorage(const ExtensionInfo& info) { - if (!info.extension_manifest.get()) - return false; - - std::string error; - scoped_refptr<const Extension> extension(Extension::Create( - info.extension_path, - info.extension_location, - *info.extension_manifest, - Extension::NO_FLAGS, - info.extension_id, - &error)); - - return extension.get() && - AppIsolationInfo::HasIsolatedStorage(extension.get()); -} - bool SiteHasIsolatedStorage(const GURL& extension_site_url, content::BrowserContext* context) { const Extension* extension = ExtensionRegistry::Get(context)->
diff --git a/extensions/browser/extension_util.h b/extensions/browser/extension_util.h index 274c1a7..c831f719 100644 --- a/extensions/browser/extension_util.h +++ b/extensions/browser/extension_util.h
@@ -16,7 +16,6 @@ namespace extensions { class Extension; -struct ExtensionInfo; namespace util { @@ -24,9 +23,6 @@ // chrome/browser/extensions/extension_util.h/cc that are only dependent on // extensions/ here. -// Returns true if the extension has isolated storage. -bool HasIsolatedStorage(const ExtensionInfo& info); - // Returns true if the site URL corresponds to an extension or app and has // isolated storage. bool SiteHasIsolatedStorage(const GURL& extension_site_url,
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc index 99783d37..9681a0e 100644 --- a/gin/modules/module_registry.cc +++ b/gin/modules/module_registry.cc
@@ -258,7 +258,7 @@ bool ModuleRegistry::AttemptToLoad(Isolate* isolate, std::unique_ptr<PendingModule> pending) { if (!CheckDependencies(pending.get())) { - pending_modules_.push_back(pending.release()); + pending_modules_.push_back(std::move(pending)); return false; } return Load(isolate, std::move(pending)); @@ -279,7 +279,7 @@ PendingModuleVector pending_modules; pending_modules.swap(pending_modules_); for (size_t i = 0; i < pending_modules.size(); ++i) { - std::unique_ptr<PendingModule> pending(pending_modules[i]); + std::unique_ptr<PendingModule> pending(std::move(pending_modules[i])); pending_modules[i] = NULL; if (AttemptToLoad(isolate, std::move(pending))) keep_trying = true;
diff --git a/gin/modules/module_registry.h b/gin/modules/module_registry.h index 9bbfd6e0..c1d3a00 100644 --- a/gin/modules/module_registry.h +++ b/gin/modules/module_registry.h
@@ -10,11 +10,11 @@ #include <memory> #include <set> #include <string> +#include <vector> #include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/observer_list.h" #include "gin/gin_export.h" #include "v8/include/v8.h" @@ -77,7 +77,7 @@ } private: - typedef ScopedVector<PendingModule> PendingModuleVector; + typedef std::vector<std::unique_ptr<PendingModule>> PendingModuleVector; typedef std::multimap<std::string, LoadModuleCallback> LoadModuleCallbackMap; explicit ModuleRegistry(v8::Isolate* isolate);
diff --git a/gpu/ipc/common/memory_stats_struct_traits.h b/gpu/ipc/common/memory_stats_struct_traits.h index 286801a..b3564cc 100644 --- a/gpu/ipc/common/memory_stats_struct_traits.h +++ b/gpu/ipc/common/memory_stats_struct_traits.h
@@ -5,6 +5,7 @@ #ifndef GPU_IPC_COMMON_MEMORY_STATS_STRUCT_TRAITS_H_ #define GPU_IPC_COMMON_MEMORY_STATS_STRUCT_TRAITS_H_ +#include "build/build_config.h" #include "gpu/ipc/common/memory_stats.h" #include "gpu/ipc/common/memory_stats.mojom-shared.h" @@ -36,7 +37,7 @@ gpu::VideoMemoryUsageStats> { static std::map<int32_t, gpu::VideoMemoryUsageStats::ProcessStats> process_map(const gpu::VideoMemoryUsageStats& stats) { -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_FUCHSIA) std::map<int32_t, gpu::VideoMemoryUsageStats::ProcessStats> map; for (const auto& pair : stats.process_map) map[static_cast<int32_t>(pair.first)] = pair.second; @@ -52,7 +53,7 @@ static bool Read(gpu::mojom::VideoMemoryUsageStatsDataView data, gpu::VideoMemoryUsageStats* out) { -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_FUCHSIA) std::map<int32_t, gpu::VideoMemoryUsageStats::ProcessStats> process_map; if (!data.ReadProcessMap(&process_map)) return false;
diff --git a/gpu/ipc/common/surface_handle.h b/gpu/ipc/common/surface_handle.h index 70659ab..ecebc066 100644 --- a/gpu/ipc/common/surface_handle.h +++ b/gpu/ipc/common/surface_handle.h
@@ -27,10 +27,13 @@ // handle generated by that. // On NaCl, we don't have native surfaces per se, but we need SurfaceHandle to // be defined, because some APIs that use it are referenced there. +// +// TODO(fuchsia): Figure out the right approach for Fuchsia. #if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) using SurfaceHandle = gfx::AcceleratedWidget; constexpr SurfaceHandle kNullSurfaceHandle = gfx::kNullAcceleratedWidget; -#elif defined(OS_MACOSX) || defined(OS_ANDROID) || defined(OS_NACL) +#elif defined(OS_MACOSX) || defined(OS_ANDROID) || defined(OS_NACL) || \ + defined(OS_FUCHSIA) using SurfaceHandle = int32_t; constexpr SurfaceHandle kNullSurfaceHandle = 0; #else
diff --git a/headless/lib/frame_id_browsertest.cc b/headless/lib/frame_id_browsertest.cc index 6a383333..5a03b39 100644 --- a/headless/lib/frame_id_browsertest.cc +++ b/headless/lib/frame_id_browsertest.cc
@@ -203,8 +203,8 @@ if (EnableInterception()) { devtools_client_->GetNetwork() ->GetExperimental() - ->EnableRequestInterception( - network::EnableRequestInterceptionParams::Builder() + ->SetRequestInterceptionEnabled( + network::SetRequestInterceptionEnabledParams::Builder() .SetEnabled(true) .Build()); }
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc index 635aeea..5d97e60e 100644 --- a/headless/lib/headless_devtools_client_browsertest.cc +++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -1378,8 +1378,8 @@ devtools_client_->GetNetwork()->Enable(); devtools_client_->GetNetwork() ->GetExperimental() - ->EnableRequestInterception( - network::EnableRequestInterceptionParams::Builder() + ->SetRequestInterceptionEnabled( + network::SetRequestInterceptionEnabledParams::Builder() .SetEnabled(true) .Build());
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 3b46ddb..c4f49c6 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -72,8 +72,12 @@ } buckets { name: "master.tryserver.chromium.mac" + # https://crbug.com/739556; make this non-experimental ASAP. + builders { + name: "ios-device" + experiment_percentage: 100 + } # https://crbug.com/739556 - # builders { name: "ios-device" } # builders { name: "ios-device-xcode-clang" } builders { name: "ios-simulator" } # builders { name: "ios-simulator-xcode-clang" }
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state.h b/ios/chrome/browser/browser_state/chrome_browser_state.h index 6f4287a..9d2a2dc 100644 --- a/ios/chrome/browser/browser_state/chrome_browser_state.h +++ b/ios/chrome/browser/browser_state/chrome_browser_state.h
@@ -13,7 +13,6 @@ #include "base/macros.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "ios/chrome/browser/net/net_types.h" #include "ios/web/public/browser_state.h" #include "net/url_request/url_request_job_factory.h"
diff --git a/ios/chrome/browser/google/google_logo_service.mm b/ios/chrome/browser/google/google_logo_service.mm index d7da9c3..1d58dfe 100644 --- a/ios/chrome/browser/google/google_logo_service.mm +++ b/ios/chrome/browser/google/google_logo_service.mm
@@ -8,14 +8,12 @@ #include "base/bind.h" #include "base/strings/sys_string_conversions.h" -#include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "components/search_engines/template_url_service.h" #include "components/search_provider_logos/google_logo_api.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" #include "ios/chrome/browser/search_engines/ui_thread_search_terms_data.h" -#include "ios/web/public/web_thread.h" #include "net/url_request/url_request_context_getter.h" #include "ui/gfx/image/image.h" @@ -100,12 +98,9 @@ return; if (!logo_tracker_) { - logo_tracker_.reset(new LogoTracker( - DoodleDirectory(), - web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE), - web::WebThread::GetBlockingPool(), browser_state_->GetRequestContext(), - std::unique_ptr<search_provider_logos::LogoDelegate>( - new IOSChromeLogoDelegate()))); + logo_tracker_ = base::MakeUnique<LogoTracker>( + DoodleDirectory(), browser_state_->GetRequestContext(), + base::MakeUnique<IOSChromeLogoDelegate>()); } logo_tracker_->SetServerAPI(
diff --git a/ios/chrome/browser/payments/BUILD.gn b/ios/chrome/browser/payments/BUILD.gn index e1ed767..33bd463 100644 --- a/ios/chrome/browser/payments/BUILD.gn +++ b/ios/chrome/browser/payments/BUILD.gn
@@ -47,7 +47,9 @@ "//components/autofill/core/browser:test_support", "//components/payments/core", "//ios/chrome/browser", + "//ios/chrome/browser/browser_state:test_support", "//ios/web", + "//ios/web/public/test/fakes", "//testing/gmock", "//testing/gtest", ]
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h index bd1b74a..d05b33b 100644 --- a/ios/chrome/browser/payments/payment_request.h +++ b/ios/chrome/browser/payments/payment_request.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/payments/core/journey_logger.h" #include "components/payments/core/payment_options_provider.h" #include "components/payments/core/payment_request_base_delegate.h" #include "components/payments/core/payments_profile_comparator.h" @@ -37,6 +38,10 @@ class ChromeBrowserState; } // namepsace ios +namespace web { +class WebState; +} // namespace web + // A protocol implementd by any UI classes that the PaymentRequest object // needs to communicate with in order to perform certain actions such as // initiating UI to request full card details for payment. @@ -55,14 +60,16 @@ // Has a copy of web::PaymentRequest as provided by the page invoking the // PaymentRequest API. Also caches credit cards and addresses provided by the // |personal_data_manager| and manages shared resources and user selections for -// the current PaymentRequest flow. It must be initialized with a non-null -// instance of |personal_data_manager| that outlives this class. +// the current PaymentRequest flow. It must be initialized with non-null +// instances of |browser_state|, |web_state|, and |personal_data_manager| that +// outlive this class. class PaymentRequest : public PaymentOptionsProvider, public PaymentRequestBaseDelegate { public: // |personal_data_manager| should not be null and should outlive this object. PaymentRequest(const web::PaymentRequest& web_payment_request, - ios::ChromeBrowserState* browser_state_, + ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager, id<PaymentRequestUIDelegate> payment_request_ui_delegate); ~PaymentRequest() override; @@ -93,6 +100,9 @@ return web_payment_request_.details; } + // Returns the JourneyLogger for this instance. + const JourneyLogger& journey_logger() const { return journey_logger_; } + // Updates the payment details of the |web_payment_request_|. It also updates // the cached references to the shipping options in |web_payment_request_| as // well as the reference to the selected shipping option. @@ -244,6 +254,9 @@ ios::ChromeBrowserState* browser_state_; // Never null and outlives this object. + web::WebState* web_state_; + + // Never null and outlives this object. autofill::PersonalDataManager* personal_data_manager_; // The PaymentRequestUIDelegate as provided by the UI object that originally @@ -299,6 +312,9 @@ PaymentsProfileComparator profile_comparator_; + // Keeps track of different stats during the lifetime of this object. + JourneyLogger journey_logger_; + DISALLOW_COPY_AND_ASSIGN(PaymentRequest); };
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm index f3b5aba..900fe519 100644 --- a/ios/chrome/browser/payments/payment_request.mm +++ b/ios/chrome/browser/payments/payment_request.mm
@@ -28,6 +28,7 @@ #import "ios/chrome/browser/payments/payment_request_util.h" #include "ios/chrome/browser/signin/signin_manager_factory.h" #include "ios/web/public/payments/payment_request.h" +#include "ios/web/public/web_state/web_state.h" #include "third_party/libaddressinput/chromium/chrome_metadata_source.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" @@ -56,10 +57,12 @@ PaymentRequest::PaymentRequest( const web::PaymentRequest& web_payment_request, ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager, id<PaymentRequestUIDelegate> payment_request_ui_delegate) : web_payment_request_(web_payment_request), browser_state_(browser_state), + web_state_(web_state), personal_data_manager_(personal_data_manager), payment_request_ui_delegate_(payment_request_ui_delegate), address_normalizer_(new AddressNormalizerImpl( @@ -70,8 +73,8 @@ selected_contact_profile_(nullptr), selected_payment_method_(nullptr), selected_shipping_option_(nullptr), - profile_comparator_(GetApplicationContext()->GetApplicationLocale(), - *this) { + profile_comparator_(GetApplicationLocale(), *this), + journey_logger_(IsIncognito(), GetLastCommittedURL(), GetUkmRecorder()) { PopulateAvailableShippingOptions(); PopulateProfileCache(); PopulateAvailableProfiles(); @@ -129,8 +132,7 @@ } const GURL& PaymentRequest::GetLastCommittedURL() const { - NOTREACHED() << "Implementation is never used"; - return GURL::EmptyGURL(); + return web_state_->GetLastCommittedURL(); } void PaymentRequest::DoFullCardRequest( @@ -150,8 +152,7 @@ GetAddressInputSource( personal_data_manager_->GetURLRequestContextGetter()) .release(), - GetAddressInputStorage().release(), - GetApplicationContext()->GetApplicationLocale()); + GetAddressInputStorage().release(), GetApplicationLocale()); } ukm::UkmRecorder* PaymentRequest::GetUkmRecorder() { @@ -203,7 +204,7 @@ base::UTF16ToASCII(web_payment_request_.details.total.amount.currency), base::UTF16ToASCII( web_payment_request_.details.total.amount.currency_system), - GetApplicationContext()->GetApplicationLocale())); + GetApplicationLocale())); } return currency_formatter_.get(); } @@ -287,8 +288,7 @@ // effectively owned by this object. payment_method_cache_.push_back(base::MakeUnique<AutofillPaymentInstrument>( method_name, credit_card, matches_merchant_card_type_exactly, - billing_profiles(), GetApplicationContext()->GetApplicationLocale(), - this)); + billing_profiles(), GetApplicationLocale(), this)); PopulateAvailablePaymentMethods();
diff --git a/ios/chrome/browser/payments/payment_request_unittest.mm b/ios/chrome/browser/payments/payment_request_unittest.mm index 61e584b..d406b7f 100644 --- a/ios/chrome/browser/payments/payment_request_unittest.mm +++ b/ios/chrome/browser/payments/payment_request_unittest.mm
@@ -4,6 +4,8 @@ #include "ios/chrome/browser/payments/payment_request.h" +#include <memory> + #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" #include "components/autofill/core/browser/autofill_test_utils.h" @@ -14,9 +16,11 @@ #include "components/payments/core/currency_formatter.h" #include "components/payments/core/payment_method_data.h" #include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -43,6 +47,9 @@ class PaymentRequestTest : public testing::Test { protected: + PaymentRequestTest() + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()) {} + // Returns PaymentDetails with one shipping option that's selected. web::PaymentDetails CreateDetailsWithShippingOption() { web::PaymentDetails details; @@ -69,19 +76,23 @@ } base::test::ScopedTaskEnvironment scoped_task_environment_; + + web::TestWebState web_state_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; }; // Tests that the payments::CurrencyFormatter is constructed with the correct // currency code and currency system. TEST_F(PaymentRequestTest, CreatesCurrencyFormatterCorrectly) { - ASSERT_EQ("en", GetApplicationContext()->GetApplicationLocale()); web::PaymentRequest web_payment_request; autofill::TestPersonalDataManager personal_data_manager; web_payment_request.details.total.amount.currency = base::ASCIIToUTF16("USD"); TestPaymentRequest payment_request1(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); + ASSERT_EQ("en", payment_request1.GetApplicationLocale()); CurrencyFormatter* currency_formatter = payment_request1.GetOrCreateCurrencyFormatter(); EXPECT_EQ(base::UTF8ToUTF16("$55.00"), currency_formatter->Format("55.00")); @@ -89,7 +100,9 @@ web_payment_request.details.total.amount.currency = base::ASCIIToUTF16("JPY"); TestPaymentRequest payment_request2(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); + ASSERT_EQ("en", payment_request2.GetApplicationLocale()); currency_formatter = payment_request2.GetOrCreateCurrencyFormatter(); EXPECT_EQ(base::UTF8ToUTF16("¥55"), currency_formatter->Format("55.00")); EXPECT_EQ("JPY", currency_formatter->formatted_currency_code()); @@ -98,7 +111,9 @@ base::ASCIIToUTF16("NOT_ISO4217"); web_payment_request.details.total.amount.currency = base::ASCIIToUTF16("USD"); TestPaymentRequest payment_request3(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); + ASSERT_EQ("en", payment_request3.GetApplicationLocale()); currency_formatter = payment_request3.GetOrCreateCurrencyFormatter(); EXPECT_EQ(base::UTF8ToUTF16("55.00"), currency_formatter->Format("55.00")); EXPECT_EQ("USD", currency_formatter->formatted_currency_code()); @@ -117,6 +132,7 @@ web_payment_request.method_data.push_back(method_datum2); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); ASSERT_EQ(2U, payment_request.supported_card_networks().size()); EXPECT_EQ("visa", payment_request.supported_card_networks()[0]); @@ -138,6 +154,7 @@ web_payment_request.method_data.push_back(method_datum1); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); ASSERT_EQ(2U, payment_request.supported_card_networks().size()); EXPECT_EQ("visa", payment_request.supported_card_networks()[0]); @@ -164,6 +181,7 @@ web_payment_request.method_data.push_back(method_datum4); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); ASSERT_EQ(2U, payment_request.supported_card_networks().size()); EXPECT_EQ("visa", payment_request.supported_card_networks()[0]); @@ -180,6 +198,7 @@ web_payment_request.method_data.push_back(method_datum1); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); // All of the basic card networks are supported. @@ -206,6 +225,7 @@ web_payment_request.method_data.push_back(method_datum1); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); // All of the basic card networks are supported, but JCB is first because it @@ -239,6 +259,7 @@ web_payment_request.method_data.push_back(method_datum2); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(3u, payment_request.supported_card_networks().size()); @@ -260,6 +281,7 @@ web_payment_request.method_data.push_back(method_datum1); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); // Only the specified networks are supported. @@ -284,6 +306,7 @@ personal_data_manager.AddTestingCreditCard(&credit_card_1); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(1U, payment_request.payment_methods().size()); @@ -308,6 +331,7 @@ personal_data_manager.AddTestingProfile(&profile_1); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(1U, payment_request.shipping_profiles().size()); EXPECT_EQ(1U, payment_request.contact_profiles().size()); @@ -344,6 +368,7 @@ web_payment_request.details = std::move(details); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); // The last one marked "selected" should be selected. EXPECT_EQ(base::UTF8ToUTF16("option:3"), @@ -367,6 +392,7 @@ // No profiles are selected because none are available! TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(nullptr, payment_request.selected_shipping_profile()); EXPECT_EQ(nullptr, payment_request.selected_contact_profile()); @@ -390,6 +416,7 @@ // address2 is selected because it has the most use count (Frecency model). TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(address2.guid(), payment_request.selected_shipping_profile()->guid()); @@ -415,6 +442,7 @@ // No shipping profile is selected because the merchant has not selected a // shipping option. However there is a suitable contact profile. TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(nullptr, payment_request.selected_shipping_profile()); EXPECT_EQ(address.guid(), payment_request.selected_contact_profile()->guid()); @@ -443,6 +471,7 @@ // Even though address1 has more use counts, address2 is selected because it // is complete. TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(address2.guid(), payment_request.selected_shipping_profile()->guid()); @@ -479,6 +508,7 @@ // phone. address2 is selected as the shipping profile because it's the most // complete for shipping. TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(address2.guid(), payment_request.selected_shipping_profile()->guid()); @@ -494,6 +524,7 @@ // No payment methods are selected because none are available! TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(nullptr, payment_request.selected_payment_method()); } @@ -513,6 +544,7 @@ // credit_card is selected because expired cards are valid for payment. TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); EXPECT_EQ(payment_request.selected_payment_method()->type(), PaymentInstrument::Type::AUTOFILL); @@ -542,6 +574,7 @@ // credit_card2 is selected because it has the most use count (Frecency // model). TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>( @@ -568,6 +601,7 @@ // Even though credit_card2 has more use counts, credit_card is selected // because it is complete. TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>( @@ -598,6 +632,7 @@ payment_request_test_util::CreateTestWebPaymentRequest(); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>( @@ -634,6 +669,7 @@ payment_request_test_util::CreateTestWebPaymentRequest(); TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>( @@ -671,6 +707,7 @@ web_payment_request.options.request_payer_phone = false; TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>( @@ -704,6 +741,7 @@ web_payment_request.options.request_shipping = false; TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>( @@ -739,6 +777,7 @@ web_payment_request.options.request_payer_phone = false; TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, &personal_data_manager); AutofillPaymentInstrument* payment_instrument = static_cast<AutofillPaymentInstrument*>(
diff --git a/ios/chrome/browser/payments/test_payment_request.h b/ios/chrome/browser/payments/test_payment_request.h index 2d119851..b669e245 100644 --- a/ios/chrome/browser/payments/test_payment_request.h +++ b/ios/chrome/browser/payments/test_payment_request.h
@@ -24,6 +24,7 @@ namespace web { class PaymentRequest; class PaymentShippingOption; +class WebState; } // namespace web class PrefService; @@ -33,13 +34,16 @@ // PaymentRequest for use in tests. class TestPaymentRequest : public PaymentRequest { public: - // |personal_data_manager| should not be null and should outlive this object. + // |browser_state|, |web_state|, and |personal_data_manager| should not be + // null and should outlive this object. TestPaymentRequest(const web::PaymentRequest& web_payment_request, ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager, id<PaymentRequestUIDelegate> payment_request_ui_delegate) : PaymentRequest(web_payment_request, browser_state, + web_state, personal_data_manager, payment_request_ui_delegate), region_data_loader_(nullptr), @@ -48,16 +52,11 @@ TestPaymentRequest(const web::PaymentRequest& web_payment_request, ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager) : TestPaymentRequest(web_payment_request, browser_state, - personal_data_manager, - nil) {} - - TestPaymentRequest(const web::PaymentRequest& web_payment_request, - autofill::PersonalDataManager* personal_data_manager) - : TestPaymentRequest(web_payment_request, - nil, + web_state, personal_data_manager, nil) {}
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 6ceff6a..e2389e0 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -3533,6 +3533,7 @@ bridge:bridge sourceFrame:[sourceView convertRect:[sourceView bounds] toView:view] parentView:view]; + _pageInfoController.dispatcher = self.dispatcher; bridge->set_controller(_pageInfoController); } @@ -3970,9 +3971,7 @@ - (IBAction)locationBarBeganEdit:(id)sender { // On handsets, if a page is currently loading it should be stopped. if (!IsIPadIdiom() && _toolbarModelIOS->IsLoading()) { - GenericChromeCommand* command = - [[GenericChromeCommand alloc] initWithTag:IDC_STOP]; - [self chromeExecuteCommand:command]; + [self.dispatcher stopLoading]; _locationBarEditCancelledLoad = YES; } } @@ -4031,6 +4030,20 @@ [[_model currentTab] goForward]; } +- (void)stopLoading { + [_model currentTab].webState->Stop(); +} + +- (void)reload { + web::WebState* webState = [_model currentTab].webState; + if (webState) { + // |check_for_repost| is true because the reload is explicitly initiated + // by the user. + webState->GetNavigationManager()->Reload(web::ReloadType::NORMAL, + true /* check_for_repost */); + } +} + #pragma mark - Command Handling - (IBAction)chromeExecuteCommand:(id)sender { @@ -4105,12 +4118,8 @@ } break; case IDC_RELOAD: { - web::WebState* webState = [_model currentTab].webState; - if (webState) - // |check_for_repost| is true because the reload is explicitly initiated - // by the user. - webState->GetNavigationManager()->Reload(web::ReloadType::NORMAL, - true /* check_for_repost */); + // Route to dispatcher until downstream code is migrated. + [self.dispatcher reload]; break; } case IDC_SHARE_PAGE: @@ -4154,9 +4163,6 @@ } break; } - case IDC_STOP: - [_model currentTab].webState->Stop(); - break; #if !defined(NDEBUG) case IDC_VIEW_SOURCE: [self viewSource];
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index ee911d0..3c97d78b 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -18,6 +18,12 @@ // Navigates forwards in the current tab's history. - (void)goForward; +// Stops loading the current web page. +- (void)stopLoading; + +// Reloads the current web page +- (void)reload; + @end #endif // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/commands/ios_command_ids.h b/ios/chrome/browser/ui/commands/ios_command_ids.h index 58a4aa3..ad25284 100644 --- a/ios/chrome/browser/ui/commands/ios_command_ids.h +++ b/ios/chrome/browser/ui/commands/ios_command_ids.h
@@ -14,7 +14,6 @@ // clang-format off #define IDC_RELOAD 33002 -#define IDC_STOP 33006 #define IDC_NEW_TAB 34014 #define IDC_FULLSCREEN 34030 #define IDC_BOOKMARK_PAGE 35000
diff --git a/ios/chrome/browser/ui/key_commands_provider.mm b/ios/chrome/browser/ui/key_commands_provider.mm index e09cb7c..06d711d4 100644 --- a/ios/chrome/browser/ui/key_commands_provider.mm +++ b/ios/chrome/browser/ui/key_commands_provider.mm
@@ -156,7 +156,7 @@ title:l10n_util::GetNSStringWithFixup( IDS_IOS_ACCNAME_RELOAD) action:^{ - execute(IDC_RELOAD); + [weakDispatcher reload]; }], ]]; @@ -247,7 +247,7 @@ modifierFlags:UIKeyModifierCommand title:nil action:^{ - execute(IDC_STOP); + [weakDispatcher stopLoading]; }], [UIKeyCommand cr_keyCommandWithInput:@"?" modifierFlags:UIKeyModifierCommand
diff --git a/ios/chrome/browser/ui/omnibox/page_info_view_controller.h b/ios/chrome/browser/ui/omnibox/page_info_view_controller.h index 50fb230..a64984d 100644 --- a/ios/chrome/browser/ui/omnibox/page_info_view_controller.h +++ b/ios/chrome/browser/ui/omnibox/page_info_view_controller.h
@@ -15,6 +15,7 @@ #import "ios/chrome/browser/ui/popup_menu/popup_menu_controller.h" @class BidiContainerView; +@protocol BrowserCommands; class PageInfoModel; // TODO(crbug.com/227827) Merge 178763: PageInfoModel has been removed in @@ -30,6 +31,9 @@ sourceFrame:(CGRect)source parentView:(UIView*)parent; +// Dispatcher for browser commands. +@property(nonatomic, weak) id<BrowserCommands> dispatcher; + // Dismisses the view. - (void)dismiss;
diff --git a/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm b/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm index baf87c3..051bb5e 100644 --- a/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/page_info_view_controller.mm
@@ -201,6 +201,7 @@ @synthesize containerView = containerView_; @synthesize popupContainer = popupContainer_; +@synthesize dispatcher = dispatcher_; - (id)initWithModel:(PageInfoModel*)model bridge:(PageInfoModelObserver*)bridge @@ -406,6 +407,7 @@ } - (void)close { + // Refactoring note: _containerView.tag is IDC_HIDE_PAGE_INFO. [containerView_ chromeExecuteCommand:containerView_]; } @@ -471,8 +473,7 @@ return nil; } UIButton* button = [[UIButton alloc] initWithFrame:CGRectZero]; - int messageId = IDS_IOS_PAGE_INFO_RELOAD; - NSInteger tag = IDC_RELOAD; + int messageId; NSString* accessibilityID = @"Reload button"; switch (buttonAction) { case PageInfoModel::BUTTON_NONE: @@ -480,26 +481,27 @@ return nil; case PageInfoModel::BUTTON_SHOW_SECURITY_HELP: messageId = IDS_LEARN_MORE; - tag = IDC_SHOW_SECURITY_HELP; + button.tag = IDC_SHOW_SECURITY_HELP; accessibilityID = @"Learn more"; + [button addTarget:nil + action:@selector(chromeExecuteCommand:) + forControlEvents:UIControlEventTouchUpInside]; break; case PageInfoModel::BUTTON_RELOAD: messageId = IDS_IOS_PAGE_INFO_RELOAD; - tag = IDC_RELOAD; accessibilityID = @"Reload button"; [button addTarget:self action:@selector(close) forControlEvents:UIControlEventTouchUpInside]; + [button addTarget:self.dispatcher + action:@selector(reload) + forControlEvents:UIControlEventTouchUpInside]; break; }; NSString* title = l10n_util::GetNSStringWithFixup(messageId); SetA11yLabelAndUiAutomationName(button, messageId, accessibilityID); [button setTitle:title forState:UIControlStateNormal]; - [button setTag:tag]; - [button addTarget:nil - action:@selector(chromeExecuteCommand:) - forControlEvents:UIControlEventTouchUpInside]; return button; }
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn index 148d730..21f86ef 100644 --- a/ios/chrome/browser/ui/payments/BUILD.gn +++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -207,6 +207,7 @@ "//ios/third_party/material_components_ios", "//ios/web", "//ios/web/public/test", + "//ios/web/public/test/fakes", "//testing/gmock", "//testing/gtest", "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm index 77865e8..4e48fa85 100644 --- a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
@@ -15,7 +15,6 @@ #include "components/autofill/core/common/autofill_constants.h" #include "components/payments/core/payments_profile_comparator.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h" #import "ios/chrome/browser/ui/payments/address_edit_mediator.h" @@ -151,7 +150,7 @@ address.SetInfo(autofill::AutofillType( AutofillTypeFromAutofillUIType(field.autofillUIType)), base::SysNSStringToUTF16(field.value), - GetApplicationContext()->GetApplicationLocale()); + self.paymentRequest->GetApplicationLocale()); } if (!self.address) {
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm index 3e44150..2d996d7d 100644 --- a/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm
@@ -17,12 +17,13 @@ #include "components/autofill/core/browser/test_region_data_loader.h" #include "components/payments/core/payments_profile_comparator.h" #include "components/prefs/pref_service.h" -#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" #import "ios/chrome/test/scoped_key_window.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -53,8 +54,12 @@ class MockTestPaymentRequest : public payments::TestPaymentRequest { public: MockTestPaymentRequest(web::PaymentRequest web_payment_request, + ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager) : payments::TestPaymentRequest(web_payment_request, + browser_state, + web_state, personal_data_manager) {} MOCK_METHOD1(AddAutofillProfile, autofill::AutofillProfile*(const autofill::AutofillProfile&)); @@ -104,16 +109,17 @@ class PaymentRequestAddressEditCoordinatorTest : public PlatformTest { protected: PaymentRequestAddressEditCoordinatorTest() - : pref_service_(autofill::test::PrefServiceForTesting()) { + : pref_service_(autofill::test::PrefServiceForTesting()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { autofill::CountryNames::SetLocaleString("en-US"); personal_data_manager_.SetTestingPrefService(pref_service_.get()); + payment_request_ = base::MakeUnique<MockTestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); profile_comparator_ = base::MakeUnique<MockPaymentsProfileComparator>( - GetApplicationContext()->GetApplicationLocale(), - *payment_request_.get()); + payment_request_->GetApplicationLocale(), *payment_request_.get()); payment_request_->SetProfileComparator(profile_comparator_.get()); test_region_data_loader_.set_synchronous_callback(true); @@ -126,10 +132,12 @@ base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; std::unique_ptr<PrefService> pref_service_; MockTestPersonalDataManager personal_data_manager_; autofill::TestRegionDataLoader test_region_data_loader_; std::unique_ptr<MockPaymentsProfileComparator> profile_comparator_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<MockTestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm index 1590f90..0a2ae33 100644 --- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -23,7 +23,6 @@ #include "components/autofill/core/browser/personal_data_manager.h" #include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h" @@ -173,7 +172,7 @@ autofill::CountryComboboxModel countryModel; countryModel.SetCountries(*_paymentRequest->GetPersonalDataManager(), base::Callback<bool(const std::string&)>(), - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); const autofill::CountryComboboxModel::CountryVector& countriesVector = countryModel.countries(); @@ -227,8 +226,7 @@ std::string unused; autofill::GetAddressComponents( base::SysNSStringToUTF8(self.selectedCountryCode), - GetApplicationContext()->GetApplicationLocale(), &addressComponents, - &unused); + _paymentRequest->GetApplicationLocale(), &addressComponents, &unused); for (size_t lineIndex = 0; lineIndex < addressComponents.GetSize(); ++lineIndex) { @@ -328,8 +326,7 @@ self.address ? base::SysUTF16ToNSString( payments::data_util::GetFormattedPhoneNumberForDisplay( - *self.address, - GetApplicationContext()->GetApplicationLocale())) + *self.address, _paymentRequest->GetApplicationLocale())) : nil; field = [[EditorField alloc] initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber @@ -352,7 +349,7 @@ fieldType:(autofill::ServerFieldType)fieldType { return profile ? base::SysUTF16ToNSString(profile->GetInfo( autofill::AutofillType(fieldType), - GetApplicationContext()->GetApplicationLocale())) + _paymentRequest->GetApplicationLocale())) : nil; }
diff --git a/ios/chrome/browser/ui/payments/billing_address_selection_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/billing_address_selection_coordinator_unittest.mm index d7fb8e70..3558927 100644 --- a/ios/chrome/browser/ui/payments/billing_address_selection_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/billing_address_selection_coordinator_unittest.mm
@@ -15,9 +15,11 @@ #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/autofill/core/browser/test_region_data_loader.h" #include "components/prefs/pref_service.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_selector_view_controller.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/OCMock/OCMock.h" @@ -33,7 +35,8 @@ PaymentRequestBillingAddressSelectionCoordinatorTest() : autofill_profile1_(autofill::test::GetFullProfile()), autofill_profile2_(autofill::test::GetFullProfile2()), - pref_service_(autofill::test::PrefServiceForTesting()) { + pref_service_(autofill::test::PrefServiceForTesting()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { personal_data_manager_.SetTestingPrefService(pref_service_.get()); // Add testing profiles to autofill::TestPersonalDataManager. Make the less // frequently used one incomplete. @@ -44,9 +47,10 @@ autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), base::string16(), "en-US"); personal_data_manager_.AddTestingProfile(&autofill_profile2_); + payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); test_region_data_loader_.set_synchronous_callback(true); payment_request_->SetRegionDataLoader(&test_region_data_loader_); @@ -79,9 +83,11 @@ autofill::AutofillProfile autofill_profile1_; autofill::AutofillProfile autofill_profile2_; + web::TestWebState web_state_; std::unique_ptr<PrefService> pref_service_; autofill::TestPersonalDataManager personal_data_manager_; autofill::TestRegionDataLoader test_region_data_loader_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/billing_address_selection_mediator_unittest.mm b/ios/chrome/browser/ui/payments/billing_address_selection_mediator_unittest.mm index 988a417..ec3af68 100644 --- a/ios/chrome/browser/ui/payments/billing_address_selection_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/billing_address_selection_mediator_unittest.mm
@@ -11,11 +11,12 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/payments/core/payments_profile_comparator.h" -#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #import "ios/chrome/browser/payments/payment_request_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/cells/autofill_profile_item.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/gtest_support.h" @@ -45,18 +46,19 @@ : autofill_profile_1_(autofill::test::GetFullProfile()), autofill_profile_2_(autofill::test::GetFullProfile2()), autofill_profile_3_(autofill::test::GetIncompleteProfile1()), - autofill_profile_4_(autofill::test::GetIncompleteProfile2()) { + autofill_profile_4_(autofill::test::GetIncompleteProfile2()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { // Add testing profiles to autofill::TestPersonalDataManager. personal_data_manager_.AddTestingProfile(&autofill_profile_1_); personal_data_manager_.AddTestingProfile(&autofill_profile_2_); personal_data_manager_.AddTestingProfile(&autofill_profile_3_); personal_data_manager_.AddTestingProfile(&autofill_profile_4_); + payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); profile_comparator_ = base::MakeUnique<FakePaymentsProfileComparator>( - GetApplicationContext()->GetApplicationLocale(), - *payment_request_.get()); + payment_request_->GetApplicationLocale(), *payment_request_.get()); payment_request_->SetProfileComparator(profile_comparator_.get()); } @@ -76,9 +78,11 @@ autofill::AutofillProfile autofill_profile_2_; autofill::AutofillProfile autofill_profile_3_; autofill::AutofillProfile autofill_profile_4_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; - std::unique_ptr<payments::TestPaymentRequest> payment_request_; std::unique_ptr<FakePaymentsProfileComparator> profile_comparator_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; + std::unique_ptr<payments::TestPaymentRequest> payment_request_; }; // Tests that the expected selectable items are created and that the index of
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm index aa06914..ee359bf1 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
@@ -15,7 +15,6 @@ #include "components/autofill/core/common/autofill_constants.h" #include "components/payments/core/payments_profile_comparator.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h" #import "ios/chrome/browser/ui/payments/contact_info_edit_mediator.h" @@ -98,7 +97,7 @@ case AutofillUITypeProfileHomePhoneWholeNumber: { const std::string countryCode = autofill::AutofillCountry::CountryCodeForLocale( - GetApplicationContext()->GetApplicationLocale()); + self.paymentRequest->GetApplicationLocale()); if (!autofill::IsValidPhoneNumber(base::SysNSStringToUTF16(field.value), countryCode)) { return l10n_util::GetNSString( @@ -140,7 +139,7 @@ profile.SetInfo(autofill::AutofillType( AutofillTypeFromAutofillUIType(field.autofillUIType)), base::SysNSStringToUTF16(field.value), - GetApplicationContext()->GetApplicationLocale()); + self.paymentRequest->GetApplicationLocale()); } if (!self.profile) {
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm index 95adbe5..3776c12 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm
@@ -16,12 +16,13 @@ #include "components/autofill/core/browser/test_region_data_loader.h" #include "components/payments/core/payments_profile_comparator.h" #include "components/prefs/pref_service.h" -#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" #import "ios/chrome/test/scoped_key_window.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -52,8 +53,12 @@ class MockTestPaymentRequest : public payments::TestPaymentRequest { public: MockTestPaymentRequest(web::PaymentRequest web_payment_request, + ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager) : payments::TestPaymentRequest(web_payment_request, + browser_state, + web_state, personal_data_manager) {} MOCK_METHOD1(AddAutofillProfile, autofill::AutofillProfile*(const autofill::AutofillProfile&)); @@ -94,15 +99,16 @@ class PaymentRequestContactInfoEditCoordinatorTest : public PlatformTest { protected: PaymentRequestContactInfoEditCoordinatorTest() - : pref_service_(autofill::test::PrefServiceForTesting()) { + : pref_service_(autofill::test::PrefServiceForTesting()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { personal_data_manager_.SetTestingPrefService(pref_service_.get()); + payment_request_ = base::MakeUnique<MockTestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); profile_comparator_ = base::MakeUnique<MockPaymentsProfileComparator>( - GetApplicationContext()->GetApplicationLocale(), - *payment_request_.get()); + payment_request_->GetApplicationLocale(), *payment_request_.get()); payment_request_->SetProfileComparator(profile_comparator_.get()); test_region_data_loader_.set_synchronous_callback(true); @@ -115,10 +121,12 @@ base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; std::unique_ptr<PrefService> pref_service_; MockTestPersonalDataManager personal_data_manager_; autofill::TestRegionDataLoader test_region_data_loader_; std::unique_ptr<MockPaymentsProfileComparator> profile_comparator_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<MockTestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm index 70a210f..af5c782 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -12,7 +12,6 @@ #include "components/autofill/core/browser/field_types.h" #include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h" #import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h" @@ -80,7 +79,7 @@ if (field.autofillUIType == AutofillUITypeProfileHomePhoneWholeNumber) { const std::string countryCode = autofill::AutofillCountry::CountryCodeForLocale( - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); field.value = base::SysUTF8ToNSString(payments::data_util::FormatPhoneForDisplay( base::SysNSStringToUTF8(field.value), countryCode)); @@ -119,8 +118,7 @@ self.profile ? base::SysUTF16ToNSString( payments::data_util::GetFormattedPhoneNumberForDisplay( - *self.profile, - GetApplicationContext()->GetApplicationLocale())) + *self.profile, _paymentRequest->GetApplicationLocale())) : nil; EditorField* phoneField = [[EditorField alloc] initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber @@ -163,7 +161,7 @@ fieldType:(autofill::ServerFieldType)fieldType { return profile ? base::SysUTF16ToNSString(profile->GetInfo( autofill::AutofillType(fieldType), - GetApplicationContext()->GetApplicationLocale())) + _paymentRequest->GetApplicationLocale())) : nil; }
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm index 8439a02..0dbdd7b 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
@@ -11,11 +11,13 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h" #import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h" #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/OCMock/OCMock.h" @@ -29,13 +31,18 @@ class PaymentRequestContactInfoEditMediatorTest : public PlatformTest { protected: PaymentRequestContactInfoEditMediatorTest() - : payment_request_(base::MakeUnique<payments::TestPaymentRequest>( + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()), + payment_request_(base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), + chrome_browser_state_.get(), + &web_state_, &personal_data_manager_)) {} base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator_unittest.mm index 4957c513..ca6627e 100644 --- a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator_unittest.mm
@@ -11,10 +11,12 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_selector_view_controller.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/OCMock/OCMock.h" @@ -28,20 +30,24 @@ protected: PaymentRequestContactInfoSelectionCoordinatorTest() : autofill_profile_1_(autofill::test::GetFullProfile()), - autofill_profile_2_(autofill::test::GetFullProfile2()) { + autofill_profile_2_(autofill::test::GetFullProfile2()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { // Add testing profiles to autofill::TestPersonalDataManager. personal_data_manager_.AddTestingProfile(&autofill_profile_1_); personal_data_manager_.AddTestingProfile(&autofill_profile_2_); + payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); } base::test::ScopedTaskEnvironment scoped_task_evironment_; autofill::AutofillProfile autofill_profile_1_; autofill::AutofillProfile autofill_profile_2_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/contact_info_selection_mediator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_selection_mediator_unittest.mm index de1506b..8105cfa 100644 --- a/ios/chrome/browser/ui/payments/contact_info_selection_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_selection_mediator_unittest.mm
@@ -10,10 +10,12 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #import "ios/chrome/browser/payments/payment_request_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/cells/autofill_profile_item.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/gtest_support.h" @@ -32,13 +34,15 @@ protected: PaymentRequestContactInfoSelectionMediatorTest() : autofill_profile_1_(autofill::test::GetFullProfile()), - autofill_profile_2_(autofill::test::GetFullProfile2()) { + autofill_profile_2_(autofill::test::GetFullProfile2()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { // Add testing profiles to autofill::TestPersonalDataManager. personal_data_manager_.AddTestingProfile(&autofill_profile_1_); personal_data_manager_.AddTestingProfile(&autofill_profile_2_); + payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); // Override the selected contact profile. payment_request_->set_selected_contact_profile( payment_request_->contact_profiles()[1]); @@ -57,7 +61,9 @@ autofill::AutofillProfile autofill_profile_1_; autofill::AutofillProfile autofill_profile_2_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm index a84724d9..8ac85445 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
@@ -18,7 +18,6 @@ #include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/payment_instrument.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h" #import "ios/chrome/browser/ui/payments/credit_card_edit_mediator.h" @@ -223,12 +222,12 @@ creditCard.SetInfo( autofill::AutofillType(autofill::CREDIT_CARD_EXP_MONTH), base::SysNSStringToUTF16(expMonth), - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); NSString* expYear = fieldComponents[1]; creditCard.SetInfo( autofill::AutofillType(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR), base::SysNSStringToUTF16(expYear), - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); } else if (field.autofillUIType == AutofillUITypeCreditCardSaveToChrome) { saveCreditCard = [field.value boolValue]; } else if (field.autofillUIType == AutofillUITypeCreditCardBillingAddress) { @@ -237,7 +236,7 @@ creditCard.SetInfo(autofill::AutofillType(AutofillTypeFromAutofillUIType( field.autofillUIType)), base::SysNSStringToUTF16(field.value), - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); } }
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm index 73e990b..cad7274 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm
@@ -14,11 +14,13 @@ #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/payment_instrument.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h" #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" #import "ios/chrome/test/scoped_key_window.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -40,8 +42,12 @@ class MockPaymentRequest : public payments::TestPaymentRequest { public: MockPaymentRequest(web::PaymentRequest web_payment_request, + ios::ChromeBrowserState* browser_state, + web::WebState* web_state, autofill::PersonalDataManager* personal_data_manager) : payments::TestPaymentRequest(web_payment_request, + browser_state, + web_state, personal_data_manager) {} MOCK_METHOD1( AddAutofillPaymentInstrument, @@ -109,15 +115,18 @@ class PaymentRequestCreditCardEditCoordinatorTest : public PlatformTest { protected: - PaymentRequestCreditCardEditCoordinatorTest() { + PaymentRequestCreditCardEditCoordinatorTest() + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { payment_request_ = base::MakeUnique<MockPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); } base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; MockTestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<MockPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm index 6d6c970..cf087c9d 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
@@ -13,7 +13,6 @@ #include "components/payments/core/payment_request_data_util.h" #include "components/payments/core/strings_util.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/payments/payment_request_util.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h" @@ -266,10 +265,9 @@ // Card holder name field. NSString* creditCardName = - _creditCard - ? autofill::GetCreditCardName( - *_creditCard, GetApplicationContext()->GetApplicationLocale()) - : nil; + _creditCard ? autofill::GetCreditCardName( + *_creditCard, _paymentRequest->GetApplicationLocale()) + : nil; fieldKey = [NSNumber numberWithInt:AutofillUITypeCreditCardHolderFullName]; EditorField* creditCardNameField = self.fieldsMap[fieldKey]; if (!creditCardNameField) {
diff --git a/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm b/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm index d84f5e08..118a7fa 100644 --- a/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm +++ b/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm
@@ -78,10 +78,8 @@ class PaymentRequestFullCardRequesterTest : public ChromeWebTest { protected: PaymentRequestFullCardRequesterTest() - : credit_card_(autofill::test::GetCreditCard()) { - TestChromeBrowserState::Builder test_cbs_builder; - chrome_browser_state_ = test_cbs_builder.Build(); - } + : credit_card_(autofill::test::GetCreditCard()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) {} void SetUp() override { ChromeWebTest::SetUp();
diff --git a/ios/chrome/browser/ui/payments/payment_items_display_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/payment_items_display_coordinator_unittest.mm index ea41a4f4..5f6ebbe2 100644 --- a/ios/chrome/browser/ui/payments/payment_items_display_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_items_display_coordinator_unittest.mm
@@ -11,11 +11,13 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_items_display_view_controller.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/OCMock/OCMock.h" @@ -27,15 +29,18 @@ class PaymentRequestPaymentItemsDisplayCoordinatorTest : public PlatformTest { protected: - PaymentRequestPaymentItemsDisplayCoordinatorTest() { + PaymentRequestPaymentItemsDisplayCoordinatorTest() + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); } base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/payment_items_display_view_controller_unittest.mm b/ios/chrome/browser/ui/payments/payment_items_display_view_controller_unittest.mm index 5d3a679..ef7d488 100644 --- a/ios/chrome/browser/ui/payments/payment_items_display_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_items_display_view_controller_unittest.mm
@@ -9,6 +9,7 @@ #include "base/test/scoped_task_environment.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" @@ -17,6 +18,7 @@ #import "ios/chrome/browser/ui/payments/payment_items_display_view_controller_data_source.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -45,10 +47,13 @@ class PaymentRequestPaymentItemsDisplayViewControllerTest : public CollectionViewControllerTest { protected: + PaymentRequestPaymentItemsDisplayViewControllerTest() + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()) {} + CollectionViewController* InstantiateController() override { payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); mediator_ = [[TestPaymentItemsDisplayMediator alloc] init]; PaymentItemsDisplayViewController* viewController = [ [PaymentItemsDisplayViewController alloc] initWithPayButtonEnabled:YES]; @@ -63,7 +68,9 @@ base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; TestPaymentItemsDisplayMediator* mediator_ = nil; };
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm index 616e75ca..d3c6296 100644 --- a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm
@@ -13,11 +13,13 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/payments/core/payment_instrument.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_selector_view_controller.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/OCMock/OCMock.h" @@ -33,7 +35,8 @@ PaymentRequestPaymentMethodSelectionCoordinatorTest() : autofill_profile_(autofill::test::GetFullProfile()), credit_card1_(autofill::test::GetCreditCard()), - credit_card2_(autofill::test::GetCreditCard2()) { + credit_card2_(autofill::test::GetCreditCard2()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { // Add testing credit cards to autofill::TestPersonalDataManager. Make the // less frequently used one incomplete. credit_card1_.set_use_count(10U); @@ -44,7 +47,7 @@ personal_data_manager_.AddTestingCreditCard(&credit_card2_); payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); } base::test::ScopedTaskEnvironment scoped_task_evironment_; @@ -52,7 +55,9 @@ autofill::AutofillProfile autofill_profile_; autofill::CreditCard credit_card1_; autofill::CreditCard credit_card2_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm index f307efdb..266bb6b 100644 --- a/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm
@@ -31,6 +31,7 @@ #import "ios/chrome/test/scoped_key_window.h" #import "ios/testing/ocmock_complex_type_helper.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #import "ios/web/public/test/test_web_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -100,11 +101,11 @@ TestChromeBrowserState::Builder test_cbs_builder; test_cbs_builder.AddTestingFactory(ios::SigninManagerFactory::GetInstance(), &ios::BuildFakeSigninManager); - browser_state_ = test_cbs_builder.Build(); + chrome_browser_state_ = test_cbs_builder.Build(); payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - browser_state_.get(), &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); payment_request_->SetPrefService(pref_service_.get()); } @@ -112,10 +113,11 @@ autofill::AutofillProfile autofill_profile_; autofill::CreditCard credit_card_; + web::TestWebState web_state_; std::unique_ptr<PrefService> pref_service_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; - std::unique_ptr<ios::ChromeBrowserState> browser_state_; }; // Tests that invoking start and stop on the coordinator presents and @@ -129,7 +131,7 @@ PaymentRequestCoordinator* coordinator = [[PaymentRequestCoordinator alloc] initWithBaseViewController:base_view_controller]; [coordinator setPaymentRequest:payment_request_.get()]; - [coordinator setBrowserState:browser_state_.get()]; + [coordinator setBrowserState:chrome_browser_state_.get()]; [coordinator start]; // Spin the run loop to trigger the animation. @@ -296,7 +298,7 @@ EXPECT_EQ(coordinator, callerCoordinator); }]; [coordinator setDelegate:delegate_mock]; - [coordinator setBrowserState:browser_state_.get()]; + [coordinator setBrowserState:chrome_browser_state_.get()]; [coordinator start]; // Spin the run loop to trigger the animation.
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm index c4c252b..fb191ef 100644 --- a/ios/chrome/browser/ui/payments/payment_request_manager.mm +++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -29,7 +29,6 @@ #include "components/payments/core/payment_request_base_delegate.h" #include "components/payments/core/payment_request_data_util.h" #include "components/prefs/pref_service.h" -#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/autofill/validation_rules_storage_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" @@ -380,7 +379,7 @@ const std::string default_country_code = autofill::AutofillCountry::CountryCodeForLocale( - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); _addressNormalizationManager = base::MakeUnique<payments::AddressNormalizationManager>( @@ -410,7 +409,7 @@ } _paymentRequest = base::MakeUnique<payments::PaymentRequest>( - webPaymentRequest, _browserState, _personalDataManager, self); + webPaymentRequest, _browserState, _webState, _personalDataManager, self); return YES; } @@ -734,7 +733,7 @@ paymentResponse.shipping_address = payments::data_util::GetPaymentAddressFromAutofillProfile( _pendingPaymentResponse.shippingAddress, - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); web::PaymentShippingOption* shippingOption = _paymentRequest->selected_shipping_option(); @@ -745,7 +744,7 @@ if (_paymentRequest->request_payer_name()) { paymentResponse.payer_name = _pendingPaymentResponse.contactAddress.GetInfo( autofill::AutofillType(autofill::NAME_FULL), - GetApplicationContext()->GetApplicationLocale()); + _paymentRequest->GetApplicationLocale()); } if (_paymentRequest->request_payer_email()) { @@ -777,7 +776,7 @@ (const autofill::AutofillProfile&)shippingAddress { payments::PaymentAddress address = payments::data_util::GetPaymentAddressFromAutofillProfile( - shippingAddress, GetApplicationContext()->GetApplicationLocale()); + shippingAddress, _paymentRequest->GetApplicationLocale()); [_paymentRequestJsManager updateShippingAddress:address completionHandler:nil]; [self setUnblockEventQueueTimer];
diff --git a/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm index 1533918..4a5bbdb 100644 --- a/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm
@@ -34,6 +34,7 @@ #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h" #import "ios/chrome/browser/ui/payments/cells/price_item.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "ui/base/l10n/l10n_util.h" @@ -68,7 +69,7 @@ payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - chrome_browser_state_.get(), &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); payment_request_->SetPrefService(pref_service_.get()); mediator_ = [[PaymentRequestMediator alloc] @@ -81,10 +82,11 @@ autofill::AutofillProfile autofill_profile_; autofill::CreditCard credit_card_; + web::TestWebState web_state_; std::unique_ptr<PrefService> pref_service_; autofill::TestPersonalDataManager personal_data_manager_; - std::unique_ptr<payments::TestPaymentRequest> payment_request_; std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; + std::unique_ptr<payments::TestPaymentRequest> payment_request_; PaymentRequestMediator* mediator_; };
diff --git a/ios/chrome/browser/ui/payments/payment_request_view_controller_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_view_controller_unittest.mm index 42f7cbf5..b944235 100644 --- a/ios/chrome/browser/ui/payments/payment_request_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_view_controller_unittest.mm
@@ -15,6 +15,7 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/autofill/cells/status_item.h" @@ -29,6 +30,7 @@ #import "ios/chrome/browser/ui/payments/payment_request_view_controller_data_source.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" @@ -141,14 +143,15 @@ protected: PaymentRequestViewControllerTest() : autofill_profile_(autofill::test::GetFullProfile()), - credit_card_(autofill::test::GetCreditCard()) { + credit_card_(autofill::test::GetCreditCard()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { // Add testing profile and credit card to autofill::TestPersonalDataManager. personal_data_manager_.AddTestingProfile(&autofill_profile_); personal_data_manager_.AddTestingCreditCard(&credit_card_); payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); mediator_ = [[TestPaymentRequestMediator alloc] init]; } @@ -169,7 +172,9 @@ autofill::AutofillProfile autofill_profile_; autofill::CreditCard credit_card_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; TestPaymentRequestMediator* mediator_; };
diff --git a/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator_unittest.mm index 4eb6957..7c94a2e 100644 --- a/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator_unittest.mm
@@ -15,9 +15,11 @@ #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/autofill/core/browser/test_region_data_loader.h" #include "components/prefs/pref_service.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_selector_view_controller.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "third_party/ocmock/OCMock/OCMock.h" @@ -33,7 +35,8 @@ PaymentRequestShippingAddressSelectionCoordinatorTest() : autofill_profile1_(autofill::test::GetFullProfile()), autofill_profile2_(autofill::test::GetFullProfile2()), - pref_service_(autofill::test::PrefServiceForTesting()) { + pref_service_(autofill::test::PrefServiceForTesting()), + chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { personal_data_manager_.SetTestingPrefService(pref_service_.get()); // Add testing profiles to autofill::TestPersonalDataManager. Make the less // frequently used one incomplete. @@ -44,9 +47,10 @@ autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), base::string16(), "en-US"); personal_data_manager_.AddTestingProfile(&autofill_profile2_); + payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); test_region_data_loader_.set_synchronous_callback(true); payment_request_->SetRegionDataLoader(&test_region_data_loader_); @@ -60,9 +64,11 @@ autofill::AutofillProfile autofill_profile1_; autofill::AutofillProfile autofill_profile2_; + web::TestWebState web_state_; std::unique_ptr<PrefService> pref_service_; autofill::TestPersonalDataManager personal_data_manager_; autofill::TestRegionDataLoader test_region_data_loader_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator_unittest.mm index f11631f..e65ce1b5 100644 --- a/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator_unittest.mm
@@ -11,11 +11,13 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/payments/payment_request.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/payments/payment_request_selector_view_controller.h" #include "ios/web/public/payments/payment_request.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -29,15 +31,18 @@ class PaymentRequestShippingOptionSelectionCoordinatorTest : public PlatformTest { protected: - PaymentRequestShippingOptionSelectionCoordinatorTest() { + PaymentRequestShippingOptionSelectionCoordinatorTest() + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()) { payment_request_ = base::MakeUnique<payments::TestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), - &personal_data_manager_); + chrome_browser_state_.get(), &web_state_, &personal_data_manager_); } base::test::ScopedTaskEnvironment scoped_task_evironment_; + web::TestWebState web_state_; autofill::TestPersonalDataManager personal_data_manager_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<payments::TestPaymentRequest> payment_request_; };
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_controller.h b/ios/chrome/browser/ui/popup_menu/popup_menu_controller.h index a3fdafb..31ab294f 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_controller.h +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_controller.h
@@ -7,6 +7,7 @@ #import <UIKit/UIKit.h> +@protocol BrowserCommands; @class PopupMenuController; @class PopupMenuView; @@ -32,6 +33,8 @@ @property(nonatomic, readonly, strong) UIButton* backgroundButton; // Delegate for the popup menu. @property(nonatomic, weak) id<PopupMenuDelegate> delegate; +// Dispatcher for browser commands. +@property(nonatomic, weak) id<BrowserCommands> dispatcher; // Initializes the PopupMenuController and adds its views inside of parent. - (id)initWithParentView:(UIView*)parent;
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm index 2ae1512..c4f80a6 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_controller.mm
@@ -67,6 +67,7 @@ @synthesize backgroundButton = backgroundButton_; @synthesize popupContainer = popupContainer_; @synthesize delegate = delegate_; +@synthesize dispatcher = dispatcher_; - (id)initWithParentView:(UIView*)parent { return [self initWithParentView:parent
diff --git a/ios/chrome/browser/ui/qr_scanner/README.md b/ios/chrome/browser/ui/qr_scanner/README.md index 91c3f2c..d3f7b13 100644 --- a/ios/chrome/browser/ui/qr_scanner/README.md +++ b/ios/chrome/browser/ui/qr_scanner/README.md
@@ -258,6 +258,8 @@ The following metrics are collected: +* `IOS.Spotlight.Action` when the user opens the QR scanner from searching for + it in Spotlight. * `ApplicationShortcut.ScanQRCodePressed` when the user opens the QR scanner from 3D Touch application shortcuts. * `MobileQRScannerClose` when the user closes the QR scanner without scanning
diff --git a/ios/chrome/browser/ui/reader_mode/reader_mode_checker.mm b/ios/chrome/browser/ui/reader_mode/reader_mode_checker.mm index 8c207d6..7c66279 100644 --- a/ios/chrome/browser/ui/reader_mode/reader_mode_checker.mm +++ b/ios/chrome/browser/ui/reader_mode/reader_mode_checker.mm
@@ -148,6 +148,7 @@ CheckIsDistillableOG(receiver); break; case dom_distiller::DistillerHeuristicsType::ADABOOST_MODEL: + case dom_distiller::DistillerHeuristicsType::ALL_ARTICLES: CheckIsDistillableDetector(receiver); break; case dom_distiller::DistillerHeuristicsType::ALWAYS_TRUE:
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm index 97b6ec12..898ffc46 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -345,10 +345,7 @@ waitForWebViewContainingText:base::SysNSStringToUTF8(contentToKeep)]; [ChromeEarlGrey waitForStaticHTMLViewNotContainingText:contentToKeep]; } else { - // TODO(crbug.com/714157): Remove matcher that asserts grey_nil(). - [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewContainingText( - kContentToKeep)] - assertWithMatcher:grey_nil()]; + [ChromeEarlGrey waitForWebViewNotContainingText:kContentToKeep]; [ChromeEarlGrey waitForStaticHTMLViewContainingText:contentToKeep]; }
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm index d3cdf8d1..9b526c8 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
@@ -594,7 +594,8 @@ [configuration setToolsMenuButton:toolsMenuButton_]; toolsPopupController_ = - [[ToolsPopupController alloc] initWithConfiguration:configuration]; + [[ToolsPopupController alloc] initWithConfiguration:configuration + dispatcher:self.dispatcher]; [toolsPopupController_ setDelegate:self];
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm index d29d4d4..a067d08 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -508,8 +508,6 @@ // Assign tags before calling -setUpButton, since only buttons with tags // have -chromeExecuteCommand added as a target. - [_reloadButton setTag:IDC_RELOAD]; - [_stopButton setTag:IDC_STOP]; [_starButton setTag:IDC_BOOKMARK_PAGE]; [_voiceSearchButton setTag:IDC_VOICE_SEARCH]; @@ -538,6 +536,14 @@ hasDisabledImage:YES synchronously:NO]; [_stopButton setHidden:YES]; + + // Assign targets for buttons using the dispatcher. + [_stopButton addTarget:self.dispatcher + action:@selector(stopLoading) + forControlEvents:UIControlEventTouchUpInside]; + [_reloadButton addTarget:self.dispatcher + action:@selector(reload) + forControlEvents:UIControlEventTouchUpInside]; } else { [_forwardButton setAlpha:0.0]; }
diff --git a/ios/chrome/browser/ui/tools_menu/request_desktop_mobile_site_egtest.mm b/ios/chrome/browser/ui/tools_menu/request_desktop_mobile_site_egtest.mm index cf2c07b..2c6b5a8 100644 --- a/ios/chrome/browser/ui/tools_menu/request_desktop_mobile_site_egtest.mm +++ b/ios/chrome/browser/ui/tools_menu/request_desktop_mobile_site_egtest.mm
@@ -27,8 +27,6 @@ #error "This file requires ARC support." #endif -using chrome_test_util::WebViewContainingText; - namespace { const char kUserAgentTestURL[] = @@ -95,20 +93,17 @@ [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://1.com")]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; // Verify that desktop user agent propagates. [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://2.com")]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; } // Tests that requesting desktop site of a page works and desktop user agent @@ -120,21 +115,18 @@ [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://1.com")]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; // Verify that desktop user agent does not propagate to new tab. [ChromeEarlGreyUI openNewTab]; [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://2.com")]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; } // Tests that requesting desktop site of a page works and going back re-opens @@ -146,21 +138,18 @@ [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://1.com")]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; // Verify that going back returns to the mobile site. [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; } // Tests that requesting mobile site of a page works and the user agent @@ -176,27 +165,23 @@ [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://1.com")]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; // Request and verify reception of the mobile site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestMobileButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Verify that mobile user agent propagates. [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://2.com")]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; } // Tests that requesting mobile site of a page works and going back re-opens @@ -212,28 +197,24 @@ [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://1.com")]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; // Request and verify reception of the mobile site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestMobileButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Verify that going back returns to the desktop site. [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; } // Tests that requesting desktop site button is not enabled on new tab pages. @@ -264,15 +245,13 @@ web::test::SetUpFileBasedHttpServer(); [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kUserAgentTestURL)]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; } // Tests that navigator.appVersion JavaScript API returns correct string for @@ -285,22 +264,19 @@ web::test::SetUpFileBasedHttpServer(); [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kUserAgentTestURL)]; // Verify initial reception of the mobile site. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; // Request and verify reception of the desktop site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestDesktopButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDesktopSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDesktopSiteLabel]; // Request and verify reception of the mobile site. [ChromeEarlGreyUI openToolsMenu]; [[EarlGrey selectElementWithMatcher:RequestMobileButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kMobileSiteLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kMobileSiteLabel]; } @end
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_constants.h b/ios/chrome/browser/ui/tools_menu/tools_menu_constants.h index 318b8bf..b7904b6 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_constants.h +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_constants.h
@@ -38,4 +38,11 @@ // Request mobile item accessibility Identifier. extern NSString* const kToolsMenuRequestMobileId; +// Identifiers for tools menu items (for metrics purposes). +typedef NS_ENUM(int, ToolsMenuItemID) { + // All of these values must be < 0. + TOOLS_STOP_ITEM = -1, + TOOLS_RELOAD_ITEM = -2, +}; + #endif // IOS_CHROME_BROWSER_UI_TOOLS_MENU_TOOLS_MENU_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h index 5c3905e..f4d9918 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h
@@ -7,6 +7,7 @@ #import <UIKit/UIKit.h> +@protocol BrowserCommands; @class ToolsMenuConfiguration; // TODO(crbug.com/228521): Remove this once the new command/metric handling is @@ -59,6 +60,9 @@ @property(nonatomic, weak) id<ToolsPopupTableDelegate> delegate; +// Dispatcher for browser commands. +@property(nonatomic, weak) id<BrowserCommands> dispatcher; + // Initializes the Tools popup menu. - (void)initializeMenuWithConfiguration:(ToolsMenuConfiguration*)configuration;
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm index 8f0e860..3928cfaa 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm
@@ -14,6 +14,7 @@ #include "ios/chrome/browser/experimental_flags.h" #import "ios/chrome/browser/ui/animation_util.h" #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#import "ios/chrome/browser/ui/commands/browser_commands.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notification_delegate.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notifier.h" @@ -133,6 +134,7 @@ @synthesize toolbarType = _toolbarType; @synthesize menuItems = _menuItems; @synthesize delegate = _delegate; +@synthesize dispatcher = _dispatcher; @synthesize requestStartTime = _requestStartTime; #pragma mark Public methods @@ -459,16 +461,23 @@ [toolsButton removeTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; - for (UIButton* button in [[self toolsCell] allButtons]) { + ToolsMenuViewToolsCell* toolsCell = [self toolsCell]; + for (UIButton* button in [toolsCell allButtons]) { [button removeTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; } + [toolsCell.stopButton removeTarget:self.dispatcher + action:@selector(stopLoading) + forControlEvents:UIControlEventTouchUpInside]; + [toolsCell.reloadButton removeTarget:self.dispatcher + action:@selector(reload) + forControlEvents:UIControlEventTouchUpInside]; } #pragma mark - Button event handling -- (IBAction)buttonPressed:(id)sender { +- (void)buttonPressed:(id)sender { int commandId = [sender tag]; DCHECK(commandId); // The bookmark command workaround is only needed for metrics; remap it @@ -478,12 +487,15 @@ if (commandId == IDC_TEMP_EDIT_BOOKMARK) [sender setTag:IDC_BOOKMARK_PAGE]; // Do nothing when tapping the tools menu a second time. - if (commandId != IDC_SHOW_TOOLS_MENU) { + // Do not use -chromeExecuteCommand: for tags < 0 -- that is, items that have + // been refactored to use the dispatcher. + if (commandId != IDC_SHOW_TOOLS_MENU && commandId > 0) { [self chromeExecuteCommand:sender]; } if (commandId == IDC_TEMP_EDIT_BOOKMARK) [sender setTag:IDC_TEMP_EDIT_BOOKMARK]; + // Do any metrics logging for the command, and then close the menu. [_delegate commandWasSelected:commandId]; } @@ -576,11 +588,22 @@ ToolsMenuViewToolsCell* cell = [view dequeueReusableCellWithReuseIdentifier:kToolsItemCellID forIndexPath:path]; + // Add specific target/action dispatch for buttons refactored away from + // ChromeExecuteCommand. These need to be added *before* -buttonPressed:, + // because -buttonPressed: closes the popup menu, which will usually + // destroy the buttons before any other actions can be called. + [cell.stopButton addTarget:self.dispatcher + action:@selector(stopLoading) + forControlEvents:UIControlEventTouchUpInside]; + [cell.reloadButton addTarget:self.dispatcher + action:@selector(reload) + forControlEvents:UIControlEventTouchUpInside]; for (UIButton* button in [cell allButtons]) { [button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; } + return cell; }
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_view_tools_cell.mm b/ios/chrome/browser/ui/tools_menu/tools_menu_view_tools_cell.mm index 2ae9d1b..7d4c069 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_view_tools_cell.mm +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_view_tools_cell.mm
@@ -8,6 +8,7 @@ #include "ios/chrome/browser/ui/commands/ios_command_ids.h" #include "ios/chrome/browser/ui/rtl_geometry.h" #include "ios/chrome/browser/ui/toolbar/toolbar_resource_macros.h" +#include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -64,14 +65,14 @@ int reload[2][3] = TOOLBAR_IDR_TWO_STATE(RELOAD); _reloadButton = [self newButtonForImageIds:reload - commandID:IDC_RELOAD + commandID:TOOLS_RELOAD_ITEM accessibilityLabelID:IDS_IOS_ACCNAME_RELOAD automationName:@"Reload" reverseForRTL:YES]; int stop[2][3] = TOOLBAR_IDR_TWO_STATE(STOP); _stopButton = [self newButtonForImageIds:stop - commandID:IDC_STOP + commandID:TOOLS_STOP_ITEM accessibilityLabelID:IDS_IOS_ACCNAME_STOP automationName:@"Stop"];
diff --git a/ios/chrome/browser/ui/tools_menu/tools_popup_controller.h b/ios/chrome/browser/ui/tools_menu/tools_popup_controller.h index e91c6441ed..4bc35c7 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_popup_controller.h +++ b/ios/chrome/browser/ui/tools_menu/tools_popup_controller.h
@@ -12,6 +12,7 @@ // The a11y ID of the tools menu table view (used by integration tests). extern NSString* const kToolsMenuTableViewId; +@protocol BrowserCommands; @class ToolsMenuConfiguration; // The view controller for the tools menu within the top toolbar. @@ -23,7 +24,8 @@ // Initializes the popup with the given |configuration|, a set of information // used to determine the appearance of the menu and the entries displayed. -- (instancetype)initWithConfiguration:(ToolsMenuConfiguration*)configuration; +- (instancetype)initWithConfiguration:(ToolsMenuConfiguration*)configuration + dispatcher:(id<BrowserCommands>)dispatcher; // Called when the current tab loading state changes. - (void)setIsTabLoading:(BOOL)isTabLoading;
diff --git a/ios/chrome/browser/ui/tools_menu/tools_popup_controller.mm b/ios/chrome/browser/ui/tools_menu/tools_popup_controller.mm index 96928dc..02d7b2f6 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_popup_controller.mm +++ b/ios/chrome/browser/ui/tools_menu/tools_popup_controller.mm
@@ -12,6 +12,7 @@ #include "ios/chrome/browser/ui/commands/ios_command_ids.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h" #include "ios/chrome/browser/ui/rtl_geometry.h" +#import "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/shared/chrome/browser/ui/tools_menu/tools_menu_configuration.h" @@ -46,11 +47,16 @@ @implementation ToolsPopupController @synthesize isCurrentPageBookmarked = _isCurrentPageBookmarked; -- (instancetype)initWithConfiguration:(ToolsMenuConfiguration*)configuration { +- (instancetype)initWithConfiguration:(ToolsMenuConfiguration*)configuration + dispatcher:(id<BrowserCommands>)dispatcher { DCHECK(configuration.displayView); self = [super initWithParentView:configuration.displayView]; if (self) { + // Set superclass dispatcher property. + self.dispatcher = dispatcher; _toolsMenuViewController = [[ToolsMenuViewController alloc] init]; + _toolsMenuViewController.dispatcher = self.dispatcher; + _toolsTableViewContainer = [_toolsMenuViewController view]; [_toolsTableViewContainer layer].cornerRadius = 2; [_toolsTableViewContainer layer].masksToBounds = YES; @@ -184,7 +190,7 @@ case IDC_OPTIONS: base::RecordAction(UserMetricsAction("MobileMenuSettings")); break; - case IDC_RELOAD: + case TOOLS_RELOAD_ITEM: base::RecordAction(UserMetricsAction("MobileMenuReload")); break; case IDC_SHARE_PAGE: @@ -208,7 +214,7 @@ case IDC_SHOW_OTHER_DEVICES: base::RecordAction(UserMetricsAction("MobileMenuRecentTabs")); break; - case IDC_STOP: + case TOOLS_STOP_ITEM: base::RecordAction(UserMetricsAction("MobileMenuStop")); break; case IDC_PRINT:
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm index 60805bd..86770251 100644 --- a/ios/chrome/browser/web/cache_egtest.mm +++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -28,7 +28,6 @@ #error "This file requires ARC support." #endif -using chrome_test_util::WebViewContainingText; using web::test::HttpServer; namespace { @@ -159,9 +158,7 @@ // Reloads the web view and waits for the loading to complete. // TODO(crbug.com/638674): Evaluate if this can move to shared code - (void)reloadPage { - GenericChromeCommand* reloadCommand = - [[GenericChromeCommand alloc] initWithTag:IDC_RELOAD]; - chrome_test_util::RunCommandWithActiveViewController(reloadCommand); + [chrome_test_util::BrowserCommandDispatcherForMainBVC() reload]; [ChromeEarlGrey waitForPageToFinishLoading]; }
diff --git a/ios/chrome/browser/web/forms_egtest.mm b/ios/chrome/browser/web/forms_egtest.mm index 00c468f..7cd2562 100644 --- a/ios/chrome/browser/web/forms_egtest.mm +++ b/ios/chrome/browser/web/forms_egtest.mm
@@ -30,7 +30,6 @@ using chrome_test_util::ButtonWithAccessibilityLabelId; using chrome_test_util::OmniboxText; -using chrome_test_util::WebViewContainingText; namespace { @@ -198,16 +197,14 @@ [ChromeEarlGrey loadURL:GetFormUrl()]; chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; [ChromeEarlGrey reload]; [self confirmResendWarning]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; } @@ -220,8 +217,7 @@ [ChromeEarlGrey loadURL:GetFormUrl()]; chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; @@ -229,8 +225,7 @@ [ChromeEarlGrey loadURL:GetGenericUrl()]; [ChromeEarlGrey goBack]; [self confirmResendWarning]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; } @@ -243,16 +238,14 @@ [ChromeEarlGrey loadURL:GetFormUrl()]; chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; [ChromeEarlGrey goBack]; [ChromeEarlGrey goForward]; [self confirmResendWarning]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; } @@ -265,8 +258,7 @@ [ChromeEarlGrey loadURL:GetFormUrl()]; chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; @@ -280,8 +272,7 @@ [ChromeEarlGrey waitForPageToFinishLoading]; [self confirmResendWarning]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; } @@ -293,8 +284,7 @@ [ChromeEarlGrey loadURL:GetFormUrl()]; chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; @@ -323,8 +313,7 @@ [ChromeEarlGrey waitForPageToFinishLoading]; // Verify that navigation was cancelled, and forward navigation is possible. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kSubmitButtonLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kSubmitButtonLabel]; [[EarlGrey selectElementWithMatcher:OmniboxText(GetFormUrl().GetContent())] assertWithMatcher:grey_notNil()]; [[EarlGrey selectElementWithMatcher:chrome_test_util::ForwardButton()] @@ -339,15 +328,13 @@ [ChromeEarlGrey loadURL:GetFormUrl()]; chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kDestinationText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kDestinationText]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; // Go back and verify the browser navigates to the original URL. [ChromeEarlGrey goBack]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kSubmitButtonLabel)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kSubmitButtonLabel]; [[EarlGrey selectElementWithMatcher:OmniboxText(GetFormUrl().GetContent())] assertWithMatcher:grey_notNil()]; } @@ -363,8 +350,7 @@ chrome_test_util::TapWebViewElementWithId(kSubmitButtonLabel); // Check that the redirect changes the POST to a GET. - [[EarlGrey selectElementWithMatcher:WebViewContainingText("GET")] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:"GET"]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; @@ -375,8 +361,7 @@ ButtonWithAccessibilityLabelId(IDS_HTTP_POST_WARNING_RESEND); [[EarlGrey selectElementWithMatcher:resendWarning] assertWithMatcher:grey_nil()]; - [[EarlGrey selectElementWithMatcher:WebViewContainingText("GET")] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:"GET"]; [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] assertWithMatcher:grey_notNil()]; }
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 07a9fd3..57f2156 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -156,8 +156,6 @@ "accessibility_util.mm", "chrome_actions.h", "chrome_actions.mm", - "chrome_assertions.h", - "chrome_assertions.mm", "chrome_earl_grey.h", "chrome_earl_grey.mm", "chrome_earl_grey_ui.h",
diff --git a/ios/chrome/test/earl_grey/chrome_assertions.h b/ios/chrome/test/earl_grey/chrome_assertions.h deleted file mode 100644 index fcd1689..0000000 --- a/ios/chrome/test/earl_grey/chrome_assertions.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_TEST_EARL_GREY_CHROME_ASSERTIONS_H_ -#define IOS_CHROME_TEST_EARL_GREY_CHROME_ASSERTIONS_H_ - -#import <Foundation/Foundation.h> - -namespace chrome_test_util { - -// Generates a failure if the actual number of non-incognito tabs is different -// from |expected_tab_count|. -void AssertMainTabCount(NSUInteger expected_tab_count); - -// Generates a failure if the actual number of incognito tabs is different from -// |expected_tab_count|. -void AssertIncognitoTabCount(NSUInteger expected_tab_count); - -} // namespace chrome_test_util - -#endif // IOS_CHROME_TEST_EARL_GREY_CHROME_ASSERTIONS_H_
diff --git a/ios/chrome/test/earl_grey/chrome_assertions.mm b/ios/chrome/test/earl_grey/chrome_assertions.mm deleted file mode 100644 index 2cdbc3cb..0000000 --- a/ios/chrome/test/earl_grey/chrome_assertions.mm +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/test/earl_grey/chrome_assertions.h" - -#import <EarlGrey/EarlGrey.h> - -#include "base/format_macros.h" -#import "ios/chrome/test/app/tab_test_util.h" -#import "ios/testing/wait_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace chrome_test_util { - -void AssertMainTabCount(NSUInteger expected_tab_count) { - // Allow the UI to become idle, in case any tabs are being opened or closed. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - GREYAssert(testing::WaitUntilConditionOrTimeout( - testing::kWaitForUIElementTimeout, - ^{ - return GetMainTabCount() == expected_tab_count; - }), - @"Did not receive %" PRIuNS " tabs", expected_tab_count); -} - -void AssertIncognitoTabCount(NSUInteger expected_tab_count) { - // Allow the UI to become idle, in case any tabs are being opened or closed. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - ConditionBlock condition = ^{ - return GetIncognitoTabCount() == expected_tab_count; - }; - GREYAssert(testing::WaitUntilConditionOrTimeout( - testing::kWaitForUIElementTimeout, condition), - @"Did not receive %" PRIuNS " incognito tabs", expected_tab_count); -} - -} // namespace chrome_test_util
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index c0aba2f..5e46264 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -117,9 +117,7 @@ } + (void)reload { - base::scoped_nsobject<GenericChromeCommand> reloadCommand( - [[GenericChromeCommand alloc] initWithTag:IDC_RELOAD]); - chrome_test_util::RunCommandWithActiveViewController(reloadCommand); + [chrome_test_util::BrowserCommandDispatcherForMainBVC() reload]; [ChromeEarlGrey waitForPageToFinishLoading]; }
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h index d9002c72..6c4fb37 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.h +++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -31,9 +31,6 @@ // accessibility trait UIAccessibilityTraitStaticText. id<GREYMatcher> StaticTextWithAccessibilityLabel(NSString* label); -// Returns matcher for webview containing |text|. -id<GREYMatcher> WebViewContainingText(std::string text); - // Returns matcher for webview not containing |text|. id<GREYMatcher> WebViewNotContainingText(std::string text);
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm index c9aa5e42..3a951c9 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -95,10 +95,6 @@ l10n_util::GetNSStringWithFixup(message_id)); } -id<GREYMatcher> WebViewContainingText(std::string text) { - return web::WebViewContainingText(std::move(text), GetCurrentWebState()); -} - id<GREYMatcher> WebViewNotContainingText(std::string text) { return web::WebViewNotContainingText(std::move(text), GetCurrentWebState()); }
diff --git a/ios/chrome/test/earl_grey/device_check_egtest.mm b/ios/chrome/test/earl_grey/device_check_egtest.mm index 0fee2395..e9f596f 100644 --- a/ios/chrome/test/earl_grey/device_check_egtest.mm +++ b/ios/chrome/test/earl_grey/device_check_egtest.mm
@@ -5,7 +5,6 @@ #import <XCTest/XCTest.h> #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" -#import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" #include "url/gurl.h" @@ -13,8 +12,6 @@ #error "This file requires ARC support." #endif -using chrome_test_util::WebViewContainingText; - // Test suite to verify Internet connectivity. @interface DeviceCheckTestCase : ChromeTestCase @end
diff --git a/ios/clean/chrome/browser/ui/tab/BUILD.gn b/ios/clean/chrome/browser/ui/tab/BUILD.gn index 43b3865..3788862 100644 --- a/ios/clean/chrome/browser/ui/tab/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tab/BUILD.gn
@@ -63,6 +63,7 @@ "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", "//ios/shared/chrome/browser/ui/coordinators:test_support", + "//ios/shared/chrome/browser/ui/tab:test_support", "//ios/shared/chrome/browser/ui/toolbar:test_support", "//ios/web/public/test", "//testing/gtest",
diff --git a/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm b/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm index 6da44dbb..cdacb9cd 100644 --- a/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm +++ b/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm
@@ -11,6 +11,7 @@ #import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator_test.h" +#import "ios/shared/chrome/browser/ui/tab/tab_test_util.h" #import "ios/shared/chrome/browser/ui/toolbar/toolbar_test_util.h" #include "ios/web/public/test/test_web_thread.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,24 +22,6 @@ namespace { -class StubNavigationManager : public web::TestNavigationManager { - public: - int GetItemCount() const override { return item_count_; } - bool CanGoForward() const override { return false; } - bool CanGoBack() const override { return false; } - - void LoadURLWithParams(const NavigationManager::WebLoadParams&) override { - has_loaded_url_ = true; - } - - void SetItemCount(int count) { item_count_ = count; } - bool GetHasLoadedUrl() { return has_loaded_url_; } - - private: - int item_count_; - bool has_loaded_url_; -}; - class TabCoordinatorTest : public BrowserCoordinatorTest { protected: TabCoordinatorTest() @@ -49,7 +32,7 @@ objectForKey:@"EnableBottomToolbar"]; // Initialize the web state. - auto navigation_manager = base::MakeUnique<StubNavigationManager>(); + auto navigation_manager = base::MakeUnique<TabNavigationManager>(); navigation_manager->SetItemCount(0); web_state_.SetNavigationManager(std::move(navigation_manager));
diff --git a/ios/clean/chrome/browser/ui/web_contents/BUILD.gn b/ios/clean/chrome/browser/ui/web_contents/BUILD.gn index 452ec28..7cc6f98 100644 --- a/ios/clean/chrome/browser/ui/web_contents/BUILD.gn +++ b/ios/clean/chrome/browser/ui/web_contents/BUILD.gn
@@ -50,6 +50,7 @@ "//base", "//base/test:test_support", "//ios/chrome/test/base", + "//ios/shared/chrome/browser/ui/tab:test_support", "//ios/web/public/test/fakes", "//testing/gtest", ]
diff --git a/ios/clean/chrome/browser/ui/web_contents/web_contents_mediator_unittest.mm b/ios/clean/chrome/browser/ui/web_contents/web_contents_mediator_unittest.mm index 5576ba4..b1f6f7f7 100644 --- a/ios/clean/chrome/browser/ui/web_contents/web_contents_mediator_unittest.mm +++ b/ios/clean/chrome/browser/ui/web_contents/web_contents_mediator_unittest.mm
@@ -6,7 +6,7 @@ #include "base/memory/ptr_util.h" #import "ios/clean/chrome/browser/ui/web_contents/web_contents_consumer.h" -#import "ios/web/public/test/fakes/test_navigation_manager.h" +#import "ios/shared/chrome/browser/ui/tab/tab_test_util.h" #import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" @@ -31,31 +31,15 @@ namespace { -class StubNavigationManager : public web::TestNavigationManager { - public: - int GetItemCount() const override { return item_count_; } - - void LoadURLWithParams(const NavigationManager::WebLoadParams&) override { - has_loaded_url_ = true; - } - - void SetItemCount(int count) { item_count_ = count; } - bool GetHasLoadedUrl() { return has_loaded_url_; } - - private: - int item_count_; - bool has_loaded_url_; -}; - class WebContentsMediatorTest : public PlatformTest { public: WebContentsMediatorTest() { - auto navigation_manager = base::MakeUnique<StubNavigationManager>(); + auto navigation_manager = base::MakeUnique<TabNavigationManager>(); navigation_manager->SetItemCount(0); test_web_state_.SetView([[UIView alloc] init]); test_web_state_.SetNavigationManager(std::move(navigation_manager)); - auto new_navigation_manager = base::MakeUnique<StubNavigationManager>(); + auto new_navigation_manager = base::MakeUnique<TabNavigationManager>(); new_test_web_state_.SetView([[UIView alloc] init]); new_test_web_state_.SetNavigationManager(std::move(new_navigation_manager)); @@ -63,13 +47,13 @@ } ~WebContentsMediatorTest() override { [mediator_ disconnect]; } - StubNavigationManager* navigation_manager() { - return static_cast<StubNavigationManager*>( + TabNavigationManager* navigation_manager() { + return static_cast<TabNavigationManager*>( test_web_state_.GetNavigationManager()); } - StubNavigationManager* new_navigation_manager() { - return static_cast<StubNavigationManager*>( + TabNavigationManager* new_navigation_manager() { + return static_cast<TabNavigationManager*>( new_test_web_state_.GetNavigationManager()); }
diff --git a/ios/shared/chrome/browser/ui/tab/BUILD.gn b/ios/shared/chrome/browser/ui/tab/BUILD.gn new file mode 100644 index 0000000..857b808 --- /dev/null +++ b/ios/shared/chrome/browser/ui/tab/BUILD.gn
@@ -0,0 +1,15 @@ +# 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. + +source_set("test_support") { + testonly = true + sources = [ + "tab_test_util.h", + "tab_test_util.mm", + ] + deps = [ + "//ios/web/public/test/fakes", + ] + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/shared/chrome/browser/ui/tab/tab_test_util.h b/ios/shared/chrome/browser/ui/tab/tab_test_util.h new file mode 100644 index 0000000..86e13547 --- /dev/null +++ b/ios/shared/chrome/browser/ui/tab/tab_test_util.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 IOS_SHARED_CHROME_BROWSER_UI_TAB_TAB_TEST_UTIL_H_ +#define IOS_SHARED_CHROME_BROWSER_UI_TAB_TAB_TEST_UTIL_H_ + +#import "ios/web/public/test/fakes/test_navigation_manager.h" + +class TabNavigationManager : public web::TestNavigationManager { + public: + int GetItemCount() const override; + bool CanGoForward() const override; + bool CanGoBack() const override; + + void LoadURLWithParams(const NavigationManager::WebLoadParams&) override; + void SetItemCount(int count); + bool GetHasLoadedUrl(); + + private: + int item_count_; + bool has_loaded_url_; +}; + +#endif // IOS_SHARED_CHROME_BROWSER_UI_TAB_TAB_TEST_UTIL_H_
diff --git a/ios/shared/chrome/browser/ui/tab/tab_test_util.mm b/ios/shared/chrome/browser/ui/tab/tab_test_util.mm new file mode 100644 index 0000000..69c33fb --- /dev/null +++ b/ios/shared/chrome/browser/ui/tab/tab_test_util.mm
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/shared/chrome/browser/ui/tab/tab_test_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +int TabNavigationManager::GetItemCount() const { + return item_count_; +} + +bool TabNavigationManager::CanGoBack() const { + return false; +} + +bool TabNavigationManager::CanGoForward() const { + return false; +} + +void TabNavigationManager::LoadURLWithParams( + const NavigationManager::WebLoadParams&) { + has_loaded_url_ = true; +} + +void TabNavigationManager::SetItemCount(int count) { + item_count_ = count; +} + +bool TabNavigationManager::GetHasLoadedUrl() { + return has_loaded_url_; +}
diff --git a/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.cc b/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.cc index 1e24463..5a2f062 100644 --- a/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.cc +++ b/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.cc
@@ -76,4 +76,10 @@ browser_state->GetPrefs()); } +web::BrowserState* WebViewTranslateAcceptLanguagesFactory::GetBrowserStateToUse( + web::BrowserState* context) const { + // Override to enable this service for off the record browser states. + return context; +} + } // namespace ios_web_view
diff --git a/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.h b/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.h index 08d0e6b..119b81b 100644 --- a/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.h +++ b/ios/web_view/internal/translate/web_view_translate_accept_languages_factory.h
@@ -42,6 +42,8 @@ // BrowserStateKeyedServiceFactory implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( web::BrowserState* context) const override; + web::BrowserState* GetBrowserStateToUse( + web::BrowserState* context) const override; DISALLOW_COPY_AND_ASSIGN(WebViewTranslateAcceptLanguagesFactory); };
diff --git a/ios/web_view/internal/translate/web_view_translate_ranker_factory.cc b/ios/web_view/internal/translate/web_view_translate_ranker_factory.cc index 8c701968..4efa919 100644 --- a/ios/web_view/internal/translate/web_view_translate_ranker_factory.cc +++ b/ios/web_view/internal/translate/web_view_translate_ranker_factory.cc
@@ -53,4 +53,10 @@ return std::move(ranker); } +web::BrowserState* WebViewTranslateRankerFactory::GetBrowserStateToUse( + web::BrowserState* context) const { + // Override to enable this service for off the record browser states. + return context; +} + } // namespace ios_web_view
diff --git a/ios/web_view/internal/translate/web_view_translate_ranker_factory.h b/ios/web_view/internal/translate/web_view_translate_ranker_factory.h index b51ab276..6aa7902 100644 --- a/ios/web_view/internal/translate/web_view_translate_ranker_factory.h +++ b/ios/web_view/internal/translate/web_view_translate_ranker_factory.h
@@ -39,6 +39,8 @@ // BrowserStateKeyedServiceFactory implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( web::BrowserState* context) const override; + web::BrowserState* GetBrowserStateToUse( + web::BrowserState* context) const override; DISALLOW_COPY_AND_ASSIGN(WebViewTranslateRankerFactory); };
diff --git a/media/BUILD.gn b/media/BUILD.gn index bd12c8a..8b4c81d 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -466,6 +466,7 @@ ":unit_tests", "//media/audio:unit_tests", "//media/base:unit_tests", + "//media/gpu:unit_tests", "//media/mojo:unit_tests", "//media/test:pipeline_integration_tests", "//media/test:run_all_unittests",
diff --git a/media/base/android/media_player_bridge.cc b/media/base/android/media_player_bridge.cc index d496b6c..1acdd05 100644 --- a/media/base/android/media_player_bridge.cc +++ b/media/base/android/media_player_bridge.cc
@@ -85,6 +85,11 @@ void MediaPlayerBridge::Initialize() { cookies_.clear(); + if (url_.SchemeIsBlob()) { + NOTREACHED(); + return; + } + if (url_.SchemeIsFile() || url_.SchemeIs("data")) { ExtractMediaMetadata(url_.spec()); return; @@ -92,11 +97,10 @@ media::MediaResourceGetter* resource_getter = manager()->GetMediaResourceGetter(); - if (url_.SchemeIsFileSystem() || url_.SchemeIsBlob()) { + if (url_.SchemeIsFileSystem()) { resource_getter->GetPlatformPathFromURL( - url_, - base::Bind(&MediaPlayerBridge::ExtractMediaMetadata, - weak_factory_.GetWeakPtr())); + url_, base::BindOnce(&MediaPlayerBridge::ExtractMediaMetadata, + weak_factory_.GetWeakPtr())); return; } @@ -144,12 +148,18 @@ void MediaPlayerBridge::Prepare() { DCHECK(j_media_player_bridge_.is_null()); + + if (url_.SchemeIsBlob()) { + NOTREACHED(); + return; + } + CreateJavaMediaPlayerBridge(); - if (url_.SchemeIsFileSystem() || url_.SchemeIsBlob()) { + + if (url_.SchemeIsFileSystem()) { manager()->GetMediaResourceGetter()->GetPlatformPathFromURL( - url_, - base::Bind(&MediaPlayerBridge::SetDataSource, - weak_factory_.GetWeakPtr())); + url_, base::BindOnce(&MediaPlayerBridge::SetDataSource, + weak_factory_.GetWeakPtr())); return; }
diff --git a/media/base/android/media_resource_getter.h b/media/base/android/media_resource_getter.h index 81987c9..65c3aa5 100644 --- a/media/base/android/media_resource_getter.h +++ b/media/base/android/media_resource_getter.h
@@ -10,7 +10,6 @@ #include <string> #include "base/callback.h" -#include "base/files/file_path.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "media/base/media_export.h" @@ -23,49 +22,47 @@ class MEDIA_EXPORT MediaResourceGetter { public: // Callback to get the cookies. Args: cookies string. - typedef base::Callback<void(const std::string&)> GetCookieCB; + typedef base::OnceCallback<void(const std::string&)> GetCookieCB; // Callback to get the platform path. Args: platform path. - typedef base::Callback<void(const std::string&)> GetPlatformPathCB; + typedef base::OnceCallback<void(const std::string&)> GetPlatformPathCB; // Callback to get the auth credentials. Args: username and password. - typedef base::Callback<void(const base::string16&, const base::string16&)> + typedef base::OnceCallback<void(const base::string16&, const base::string16&)> GetAuthCredentialsCB; // Callback to get the media metadata. Args: duration, width, height, and // whether the information is retrieved successfully. - typedef base::Callback<void(base::TimeDelta, int, int, bool)> + typedef base::OnceCallback<void(base::TimeDelta, int, int, bool)> ExtractMediaMetadataCB; virtual ~MediaResourceGetter(); // Method for getting the auth credentials for a URL. virtual void GetAuthCredentials(const GURL& url, - const GetAuthCredentialsCB& callback) = 0; + GetAuthCredentialsCB callback) = 0; // Method for getting the cookies for a given URL. virtual void GetCookies(const GURL& url, const GURL& first_party_for_cookies, - const GetCookieCB& callback) = 0; + GetCookieCB callback) = 0; - // Method for getting the platform path from a file system or blob URL. - virtual void GetPlatformPathFromURL( - const GURL& url, - const GetPlatformPathCB& callback) = 0; + // Method for getting the platform path from a file system URL. + virtual void GetPlatformPathFromURL(const GURL& url, + GetPlatformPathCB callback) = 0; // Extracts the metadata from a media URL. Once completed, the provided // callback function will be run. - virtual void ExtractMediaMetadata( - const std::string& url, - const std::string& cookies, - const std::string& user_agent, - const ExtractMediaMetadataCB& callback) = 0; + virtual void ExtractMediaMetadata(const std::string& url, + const std::string& cookies, + const std::string& user_agent, + ExtractMediaMetadataCB callback) = 0; // Extracts the metadata from a file descriptor. Once completed, the // provided callback function will be run. virtual void ExtractMediaMetadata(const int fd, const int64_t offset, const int64_t size, - const ExtractMediaMetadataCB& callback) = 0; + ExtractMediaMetadataCB callback) = 0; }; } // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 7031e095..61e797b 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -257,6 +257,9 @@ const base::Feature kExternalClearKeyForTesting{ "external-clear-key-for-testing", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kSupportExperimentalCdmInterface{ + "SupportExperimentalCdmInterface", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables low-delay video rendering in media pipeline on "live" stream. const base::Feature kLowDelayVideoRenderingOnLiveStream{ "low-delay-video-rendering-on-live-stream",
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 8691c07..5ec97b28 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -108,6 +108,7 @@ MEDIA_EXPORT extern const base::Feature kExternalClearKeyForTesting; MEDIA_EXPORT extern const base::Feature kLowDelayVideoRenderingOnLiveStream; MEDIA_EXPORT extern const base::Feature kMediaCastOverlayButton; +MEDIA_EXPORT extern const base::Feature kMediaEngagement; MEDIA_EXPORT extern const base::Feature kMemoryPressureBasedSourceBufferGC; MEDIA_EXPORT extern const base::Feature kMojoCdm; MEDIA_EXPORT extern const base::Feature kNewAudioRenderingMixingStrategy; @@ -115,12 +116,12 @@ MEDIA_EXPORT extern const base::Feature kOverlayFullscreenVideo; MEDIA_EXPORT extern const base::Feature kResumeBackgroundVideo; MEDIA_EXPORT extern const base::Feature kSpecCompliantCanPlayThrough; +MEDIA_EXPORT extern const base::Feature kSupportExperimentalCdmInterface; MEDIA_EXPORT extern const base::Feature kUseAndroidOverlay; MEDIA_EXPORT extern const base::Feature kUseNewMediaCache; MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy; MEDIA_EXPORT extern const base::Feature kVideoColorManagement; MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideo; -MEDIA_EXPORT extern const base::Feature kMediaEngagement; #if defined(OS_ANDROID) MEDIA_EXPORT extern const base::Feature kVideoFullscreenOrientationLock;
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 9f074c0..d21c201 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc
@@ -650,14 +650,20 @@ shared_state_.statistics.audio_memory_usage += stats.audio_memory_usage; shared_state_.statistics.video_memory_usage += stats.video_memory_usage; - base::TimeDelta old_average = + if (stats.video_frame_duration_average != kNoTimestamp) { + shared_state_.statistics.video_frame_duration_average = + stats.video_frame_duration_average; + } + + base::TimeDelta old_key_frame_distance_average = shared_state_.statistics.video_keyframe_distance_average; if (stats.video_keyframe_distance_average != kNoTimestamp) { shared_state_.statistics.video_keyframe_distance_average = stats.video_keyframe_distance_average; } - if (shared_state_.statistics.video_keyframe_distance_average != old_average) { + if (shared_state_.statistics.video_keyframe_distance_average != + old_key_frame_distance_average) { main_task_runner_->PostTask( FROM_HERE, base::Bind(&PipelineImpl::OnVideoAverageKeyframeDistanceUpdate,
diff --git a/media/base/pipeline_status.h b/media/base/pipeline_status.h index b393c79..5ef61423 100644 --- a/media/base/pipeline_status.h +++ b/media/base/pipeline_status.h
@@ -61,6 +61,7 @@ int64_t audio_memory_usage = 0; int64_t video_memory_usage = 0; base::TimeDelta video_keyframe_distance_average = kNoTimestamp; + base::TimeDelta video_frame_duration_average = kNoTimestamp; }; // Used for updating pipeline statistics; the passed value should be a delta
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 8e3eaff..7636cc4 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -790,7 +790,7 @@ done_callbacks_.push_back(callback); } -void VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) { +gpu::SyncToken VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) { DCHECK(HasTextures()); base::AutoLock locker(release_sync_token_lock_); // Must wait on the previous sync point before inserting a new sync point so @@ -799,6 +799,7 @@ if (release_sync_token_.HasData()) client->WaitSyncToken(release_sync_token_); client->GenerateSyncToken(&release_sync_token_); + return release_sync_token_; } std::string VideoFrame::AsHumanReadableString() {
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index 5895253..8f56892 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -390,11 +390,11 @@ timestamp_ = timestamp; } - // It uses |client| to insert a new sync point and potentially waits on a - // older sync point. The final sync point will be used to release this - // VideoFrame. + // It uses |client| to insert a new sync token and potentially waits on an + // older sync token. The final sync point will be used to release this + // VideoFrame. Also returns the new sync token. // This method is thread safe. Both blink and compositor threads can call it. - void UpdateReleaseSyncToken(SyncTokenClient* client); + gpu::SyncToken UpdateReleaseSyncToken(SyncTokenClient* client); // Returns a human-readable string describing |*this|. std::string AsHumanReadableString();
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 2986a27c8..28911b1 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -60,6 +60,7 @@ #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebSurfaceLayerBridge.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" @@ -259,6 +260,8 @@ params->enable_instant_source_buffer_gc()), embedded_media_experience_enabled_( params->embedded_media_experience_enabled()), + surface_layer_for_video_enabled_( + base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)), request_routing_token_cb_(params->request_routing_token_cb()), overlay_routing_token_(OverlayInfo::RoutingToken()) { DVLOG(1) << __func__; @@ -267,6 +270,9 @@ DCHECK(client_); DCHECK(delegate_); + if (surface_layer_for_video_enabled_) + bridge_ = base::WrapUnique(blink::WebSurfaceLayerBridge::Create()); + force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kForceVideoOverlays); @@ -323,8 +329,11 @@ // Destruct compositor resources in the proper order. client_->SetWebLayer(nullptr); - if (video_weblayer_) + if (!surface_layer_for_video_enabled_ && video_weblayer_) { static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider(); + } + // TODO(lethalantidote): Handle destruction of compositor for surface layer. + // https://crbug/739854. compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_); media_log_->AddEvent( @@ -1349,12 +1358,20 @@ surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size); } - DCHECK(!video_weblayer_); - video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create( - compositor_, pipeline_metadata_.video_rotation))); - video_weblayer_->layer()->SetContentsOpaque(opaque_); - video_weblayer_->SetContentsOpaqueIsFixed(true); - client_->SetWebLayer(video_weblayer_.get()); + if (!surface_layer_for_video_enabled_) { + DCHECK(!video_weblayer_); + video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create( + compositor_, pipeline_metadata_.video_rotation))); + video_weblayer_->layer()->SetContentsOpaque(opaque_); + video_weblayer_->SetContentsOpaqueIsFixed(true); + client_->SetWebLayer(video_weblayer_.get()); + } else if (bridge_->GetWebLayer()) { + bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_); + // TODO(lethalantidote): Figure out how to persist opaque setting + // without calling WebLayerImpl's SetContentsOpaueIsFixed; + // https://crbug/739859. + client_->SetWebLayer(bridge_->GetWebLayer()); + } } if (observer_) @@ -1548,8 +1565,12 @@ opaque_ = opaque; // Modify content opaqueness of cc::Layer directly so that // SetContentsOpaqueIsFixed is ignored. - if (video_weblayer_) - video_weblayer_->layer()->SetContentsOpaque(opaque_); + if (!surface_layer_for_video_enabled_) { + if (video_weblayer_) + video_weblayer_->layer()->SetContentsOpaque(opaque_); + } else if (bridge_->GetWebLayer()) { + bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_); + } } void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() { @@ -1723,10 +1744,16 @@ } gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { - if (!video_weblayer_) + if (!surface_layer_for_video_enabled_) { + if (!video_weblayer_) + return pipeline_metadata_.natural_size; + + return video_weblayer_->Bounds(); + } + if (!bridge_->GetWebLayer()) return pipeline_metadata_.natural_size; - return video_weblayer_->Bounds(); + return bridge_->GetWebLayer()->Bounds(); } void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index da0d8b6..d16807c 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -44,6 +44,7 @@ #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" #include "third_party/WebKit/public/platform/WebMediaPlayer.h" +#include "third_party/WebKit/public/platform/WebSurfaceLayerBridge.h" #include "url/gurl.h" #if defined(OS_ANDROID) // WMPI_CAST @@ -721,6 +722,10 @@ // Monitors the player events. base::WeakPtr<MediaObserver> observer_; + // Owns the weblayer and obtains/maintains SurfaceIds for + // kUseSurfaceLayerForVideo feature. + std::unique_ptr<blink::WebSurfaceLayerBridge> bridge_; + // The maximum video keyframe distance that allows triggering background // playback optimizations (non-MSE). base::TimeDelta max_keyframe_distance_to_disable_background_video_; @@ -757,6 +762,9 @@ // Whether embedded media experience is currently enabled. bool embedded_media_experience_enabled_ = false; + // Whether the use of a surface layer instead of a video layer is enabled. + bool surface_layer_for_video_enabled_ = false; + gfx::Size last_uploaded_frame_size_; base::TimeDelta last_uploaded_frame_timestamp_;
diff --git a/media/cdm/cdm_adapter.cc b/media/cdm/cdm_adapter.cc index 3003d9211..3a32303 100644 --- a/media/cdm/cdm_adapter.cc +++ b/media/cdm/cdm_adapter.cc
@@ -66,26 +66,40 @@ return cdm::kKeyIds; } -CdmPromise::Exception ToMediaExceptionType(cdm::Error error) { +CdmPromise::Exception ToMediaExceptionType(cdm::Exception exception) { + switch (exception) { + case cdm::kExceptionTypeError: + return CdmPromise::INVALID_ACCESS_ERROR; + case cdm::kExceptionNotSupportedError: + return CdmPromise::NOT_SUPPORTED_ERROR; + case cdm::kExceptionInvalidStateError: + return CdmPromise::INVALID_STATE_ERROR; + case cdm::kExceptionQuotaExceededError: + return CdmPromise::QUOTA_EXCEEDED_ERROR; + } + + NOTREACHED() << "Unexpected cdm::Exception " << exception; + return CdmPromise::INVALID_STATE_ERROR; +} + +cdm::Exception ToCdmExceptionType(cdm::Error error) { switch (error) { case cdm::kNotSupportedError: - return CdmPromise::NOT_SUPPORTED_ERROR; + return cdm::kExceptionNotSupportedError; case cdm::kInvalidStateError: - return CdmPromise::INVALID_STATE_ERROR; + return cdm::kExceptionTypeError; case cdm::kInvalidAccessError: - return CdmPromise::INVALID_ACCESS_ERROR; + return cdm::kExceptionInvalidStateError; case cdm::kQuotaExceededError: - return CdmPromise::QUOTA_EXCEEDED_ERROR; + return cdm::kExceptionQuotaExceededError; case cdm::kUnknownError: - return CdmPromise::UNKNOWN_ERROR; case cdm::kClientError: - return CdmPromise::CLIENT_ERROR; case cdm::kOutputError: - return CdmPromise::OUTPUT_ERROR; + break; } NOTREACHED() << "Unexpected cdm::Error " << error; - return CdmPromise::UNKNOWN_ERROR; + return cdm::kExceptionInvalidStateError; } CdmMessageType ToMediaMessageType(cdm::MessageType message_type) { @@ -220,7 +234,7 @@ return Decryptor::kError; case cdm::kDecodeError: return Decryptor::kError; - case cdm::kSessionError: + case cdm::kInitializationError: case cdm::kDeferredInitialization: break; } @@ -294,7 +308,7 @@ return nullptr; static_assert( - cdm::ContentDecryptionModule::Host::kVersion == cdm::Host_8::kVersion, + cdm::ContentDecryptionModule::Host::kVersion == cdm::Host_9::kVersion, "update the code below"); // Ensure IsSupportedCdmHostVersion matches implementation of this function. @@ -304,10 +318,11 @@ DCHECK( // Future version is not supported. - !IsSupportedCdmHostVersion(cdm::Host_8::kVersion + 1) && + !IsSupportedCdmHostVersion(cdm::Host_9::kVersion + 1) && // Current version is supported. - IsSupportedCdmHostVersion(cdm::Host_8::kVersion) && + IsSupportedCdmHostVersion(cdm::Host_9::kVersion) && // Include all previous supported versions (if any) here. + IsSupportedCdmHostVersion(cdm::Host_8::kVersion) && // One older than the oldest supported version is not supported. !IsSupportedCdmHostVersion(cdm::Host_8::kVersion - 1)); DCHECK(IsSupportedCdmHostVersion(host_interface_version)); @@ -317,6 +332,8 @@ switch (host_interface_version) { case cdm::Host_8::kVersion: return static_cast<cdm::Host_8*>(cdm_adapter); + case cdm::Host_9::kVersion: + return static_cast<cdm::Host_9*>(cdm_adapter); default: NOTREACHED() << "Unexpected host interface version " << host_interface_version; @@ -734,6 +751,15 @@ return base::Time::Now().ToDoubleT(); } +void CdmAdapter::OnResolveKeyStatusPromise(uint32_t promise_id, + cdm::KeyStatus key_status) { + // TODO(xhwang): Implement HDCP Policy Check. https://crbug.com/709348. + NOTIMPLEMENTED(); + cdm_promise_adapter_.RejectPromise(promise_id, + CdmPromise::NOT_SUPPORTED_ERROR, 0, + "HDCP Policy Check not implemented."); +} + void CdmAdapter::OnResolvePromise(uint32_t promise_id) { DCHECK(task_runner_->BelongsToCurrentThread()); cdm_promise_adapter_.ResolvePromise(promise_id); @@ -748,32 +774,51 @@ } void CdmAdapter::OnRejectPromise(uint32_t promise_id, - cdm::Error error, + cdm::Exception exception, uint32_t system_code, const char* error_message, uint32_t error_message_size) { DCHECK(task_runner_->BelongsToCurrentThread()); cdm_promise_adapter_.RejectPromise( - promise_id, ToMediaExceptionType(error), system_code, + promise_id, ToMediaExceptionType(exception), system_code, std::string(error_message, error_message_size)); } +void CdmAdapter::OnRejectPromise(uint32_t promise_id, + cdm::Error error, + uint32_t system_code, + const char* error_message, + uint32_t error_message_size) { + // cdm::Host_8 version. Remove when CDM_8 no longer supported. + // https://crbug.com/737296. + OnRejectPromise(promise_id, ToCdmExceptionType(error), system_code, + error_message, error_message_size); +} + +void CdmAdapter::OnSessionMessage(const char* session_id, + uint32_t session_id_size, + cdm::MessageType message_type, + const char* message, + uint32_t message_size) { + DCHECK(task_runner_->BelongsToCurrentThread()); + const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(message); + session_message_cb_.Run( + std::string(session_id, session_id_size), + ToMediaMessageType(message_type), + std::vector<uint8_t>(message_ptr, message_ptr + message_size)); +} + void CdmAdapter::OnSessionMessage(const char* session_id, uint32_t session_id_size, cdm::MessageType message_type, const char* message, uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_size) { - DCHECK(task_runner_->BelongsToCurrentThread()); - // |legacy_destination_url| is obsolete and will be removed as part of - // https://crbug.com/570216. - - const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(message); - session_message_cb_.Run( - std::string(session_id, session_id_size), - ToMediaMessageType(message_type), - std::vector<uint8_t>(message_ptr, message_ptr + message_size)); + const char* /* legacy_destination_url */, + uint32_t /* legacy_destination_url_size */) { + // cdm::Host_8 version. Remove when CDM_8 no longer supported. + // https://crbug.com/737296. + OnSessionMessage(session_id, session_id_size, message_type, message, + message_size); } void CdmAdapter::OnSessionKeysChange(const char* session_id, @@ -827,8 +872,9 @@ uint32_t system_code, const char* error_message, uint32_t error_message_size) { + // cdm::Host_8 version. Remove when CDM_8 no longer supported. + // https://crbug.com/737296. DCHECK(task_runner_->BelongsToCurrentThread()); - // Obsolete and will be removed as part of https://crbug.com/570216. } void CdmAdapter::SendPlatformChallenge(const char* service_id, @@ -888,6 +934,12 @@ return file_io.release(); } +void CdmAdapter::RequestStorageId() { + // TODO(jrummell): Implement Storage Id. https://crbug.com/478960. + NOTIMPLEMENTED(); + cdm_->OnStorageId(nullptr, 0); +} + bool CdmAdapter::AudioFramesDataToAudioFrames( std::unique_ptr<AudioFramesImpl> audio_frames, Decryptor::AudioFrames* result_frames) {
diff --git a/media/cdm/cdm_adapter.h b/media/cdm/cdm_adapter.h index 7eca3403..3210a7c 100644 --- a/media/cdm/cdm_adapter.h +++ b/media/cdm/cdm_adapter.h
@@ -48,7 +48,8 @@ class MEDIA_EXPORT CdmAdapter : public ContentDecryptionModule, public CdmContext, public Decryptor, - NON_EXPORTED_BASE(public cdm::Host_8) { + NON_EXPORTED_BASE(public cdm::Host_8), + NON_EXPORTED_BASE(public cdm::Host_9) { public: // Create the CDM using |cdm_path| and initialize it using |key_system| and // |cdm_config|. |allocator| is to be used whenever the CDM needs memory @@ -110,15 +111,49 @@ void ResetDecoder(StreamType stream_type) final; void DeinitializeDecoder(StreamType stream_type) final; - // cdm::Host_8 implementation. + // cdm::Host_9 implementation. cdm::Buffer* Allocate(uint32_t capacity) override; void SetTimer(int64_t delay_ms, void* context) override; cdm::Time GetCurrentWallTime() override; + void OnResolveKeyStatusPromise(uint32_t promise_id, + cdm::KeyStatus key_status) override; void OnResolveNewSessionPromise(uint32_t promise_id, const char* session_id, uint32_t session_id_size) override; void OnResolvePromise(uint32_t promise_id) override; void OnRejectPromise(uint32_t promise_id, + cdm::Exception exception, + uint32_t system_code, + const char* error_message, + uint32_t error_message_size) override; + void OnSessionMessage(const char* session_id, + uint32_t session_id_size, + cdm::MessageType message_type, + const char* message, + uint32_t message_size) override; + void OnSessionKeysChange(const char* session_id, + uint32_t session_id_size, + bool has_additional_usable_key, + const cdm::KeyInformation* keys_info, + uint32_t keys_info_count) override; + void OnExpirationChange(const char* session_id, + uint32_t session_id_size, + cdm::Time new_expiry_time) override; + void OnSessionClosed(const char* session_id, + uint32_t session_id_size) override; + void SendPlatformChallenge(const char* service_id, + uint32_t service_id_size, + const char* challenge, + uint32_t challenge_size) override; + void EnableOutputProtection(uint32_t desired_protection_mask) override; + void QueryOutputProtectionStatus() override; + void OnDeferredInitializationDone(cdm::StreamType stream_type, + cdm::Status decoder_status) override; + cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) override; + void RequestStorageId() override; + + // cdm::Host_8 specific implementation. + void OnRejectPromise(uint32_t promise_id, cdm::Error error, uint32_t system_code, const char* error_message, @@ -130,31 +165,12 @@ uint32_t message_size, const char* legacy_destination_url, uint32_t legacy_destination_url_size) override; - void OnSessionKeysChange(const char* session_id, - uint32_t session_id_size, - bool has_additional_usable_key, - const cdm::KeyInformation* keys_info, - uint32_t keys_info_count) override; - void OnExpirationChange(const char* session_id, - uint32_t session_id_size, - cdm::Time new_expiry_time) override; - void OnSessionClosed(const char* session_id, - uint32_t session_id_size) override; void OnLegacySessionError(const char* session_id, uint32_t session_id_size, cdm::Error error, uint32_t system_code, const char* error_message, uint32_t error_message_size) override; - void SendPlatformChallenge(const char* service_id, - uint32_t service_id_size, - const char* challenge, - uint32_t challenge_size) override; - void EnableOutputProtection(uint32_t desired_protection_mask) override; - void QueryOutputProtectionStatus() override; - void OnDeferredInitializationDone(cdm::StreamType stream_type, - cdm::Status decoder_status) override; - cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) override; private: CdmAdapter(const std::string& key_system,
diff --git a/media/cdm/cdm_wrapper.h b/media/cdm/cdm_wrapper.h index ed88f49..28c4ce8 100644 --- a/media/cdm/cdm_wrapper.h +++ b/media/cdm/cdm_wrapper.h
@@ -19,11 +19,28 @@ #define PLATFORM_DCHECK PP_DCHECK #else #include "base/logging.h" +#include "media/base/media_switches.h" // nogncheck #define PLATFORM_DCHECK DCHECK #endif namespace media { +namespace { + +bool IsExperimentalCdmInterfaceSupported() { +#if defined(USE_PPAPI_CDM_ADAPTER) +#if defined(SUPPORT_EXPERIMENTAL_CDM_INTERFACE) + return true; +#else + return false; +#endif // defined(SUPPORT_EXPERIMENTAL_CDM_INTERFACE) +#else + return base::FeatureList::IsEnabled(media::kSupportExperimentalCdmInterface); +#endif // defined(USE_PPAPI_CDM_ADAPTER) +} + +} // namespace + // Returns a pointer to the requested CDM upon success. // Returns NULL if an error occurs or the requested |cdm_interface_version| or // |key_system| is not supported or another error occurs. @@ -109,6 +126,8 @@ cdm::QueryResult result, uint32_t link_mask, uint32_t output_protection_mask) = 0; + virtual void OnStorageId(const uint8_t* storage_id, + uint32_t storage_id_size) = 0; protected: CdmWrapper() {} @@ -238,6 +257,10 @@ output_protection_mask); } + void OnStorageId(const uint8_t* storage_id, uint32_t storage_id_size) { + cdm_->OnStorageId(storage_id, storage_id_size); + } + private: CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) { PLATFORM_DCHECK(cdm_); } @@ -246,13 +269,22 @@ DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl); }; +// Overrides for cdm::Host_8 methods. +// TODO(jrummell): Remove when CDM_8 no longer supported. +// https://crbug.com/737296. + +template <> +void CdmWrapperImpl<cdm::ContentDecryptionModule_8>::OnStorageId( + const uint8_t* storage_id, + uint32_t storage_id_size) {} + CdmWrapper* CdmWrapper::Create(CreateCdmFunc create_cdm_func, const char* key_system, uint32_t key_system_size, GetCdmHostFunc get_cdm_host_func, void* user_data) { static_assert(cdm::ContentDecryptionModule::kVersion == - cdm::ContentDecryptionModule_8::kVersion, + cdm::ContentDecryptionModule_9::kVersion, "update the code below"); // Ensure IsSupportedCdmInterfaceVersion() matches this implementation. @@ -260,17 +292,32 @@ // If this check fails, update this function and DCHECK or update // IsSupportedCdmInterfaceVersion(). PLATFORM_DCHECK(!IsSupportedCdmInterfaceVersion( - cdm::ContentDecryptionModule_8::kVersion + 1) && + cdm::ContentDecryptionModule_9::kVersion + 1) && + IsSupportedCdmInterfaceVersion( + cdm::ContentDecryptionModule_9::kVersion) && IsSupportedCdmInterfaceVersion( cdm::ContentDecryptionModule_8::kVersion) && !IsSupportedCdmInterfaceVersion( cdm::ContentDecryptionModule_8::kVersion - 1)); // Try to create the CDM using the latest CDM interface version. - CdmWrapper* cdm_wrapper = - CdmWrapperImpl<cdm::ContentDecryptionModule>::Create( - create_cdm_func, key_system, key_system_size, get_cdm_host_func, - user_data); + // This is only attempted if requested. For pepper plugins, this is done + // at compile time. For mojo, it is done using a media feature setting. + CdmWrapper* cdm_wrapper = nullptr; + + if (IsExperimentalCdmInterfaceSupported()) { + cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_9>::Create( + create_cdm_func, key_system, key_system_size, get_cdm_host_func, + user_data); + } + + // If |cdm_wrapper| is NULL, try to create the CDM using older supported + // versions of the CDM interface here. + if (!cdm_wrapper) { + cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_8>::Create( + create_cdm_func, key_system, key_system_size, get_cdm_host_func, + user_data); + } return cdm_wrapper; } @@ -280,7 +327,7 @@ // does not have. // Also update supported_cdm_versions.h. static_assert(cdm::ContentDecryptionModule::kVersion == - cdm::ContentDecryptionModule_8::kVersion, + cdm::ContentDecryptionModule_9::kVersion, "ensure cdm wrapper templates have old version support"); } // namespace media
diff --git a/media/cdm/ppapi/BUILD.gn b/media/cdm/ppapi/BUILD.gn index 0b6d6b0..29f8465 100644 --- a/media/cdm/ppapi/BUILD.gn +++ b/media/cdm/ppapi/BUILD.gn
@@ -65,7 +65,10 @@ output_dir = "$root_out_dir/$clearkey_cdm_path" # Check whether the plugin's origin URL is valid. - defines = [ "CHECK_DOCUMENT_URL" ] + defines = [ + "CHECK_DOCUMENT_URL", + "SUPPORT_EXPERIMENTAL_CDM_INTERFACE", + ] deps = [ ":clearkeycdm", ":clearkeycdmadapter_resources",
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index e44d50f..cca58bd 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -548,14 +548,14 @@ cdm::Status ClearKeyCdm::InitializeAudioDecoder( const cdm::AudioDecoderConfig& audio_decoder_config) { if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem) - return cdm::kSessionError; + return cdm::kInitializationError; #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) if (!audio_decoder_) audio_decoder_.reset(new media::FFmpegCdmAudioDecoder(host_)); if (!audio_decoder_->Initialize(audio_decoder_config)) - return cdm::kSessionError; + return cdm::kInitializationError; return cdm::kSuccess; #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) @@ -572,17 +572,17 @@ cdm::Status ClearKeyCdm::InitializeVideoDecoder( const cdm::VideoDecoderConfig& video_decoder_config) { if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem) - return cdm::kSessionError; + return cdm::kInitializationError; if (video_decoder_ && video_decoder_->is_initialized()) { DCHECK(!video_decoder_->is_initialized()); - return cdm::kSessionError; + return cdm::kInitializationError; } // Any uninitialized decoder will be replaced. video_decoder_ = CreateVideoDecoder(host_, video_decoder_config); if (!video_decoder_) - return cdm::kSessionError; + return cdm::kInitializationError; return cdm::kSuccess; }
diff --git a/media/cdm/ppapi/ppapi_cdm_adapter.cc b/media/cdm/ppapi/ppapi_cdm_adapter.cc index aaa39e2..4698653 100644 --- a/media/cdm/ppapi/ppapi_cdm_adapter.cc +++ b/media/cdm/ppapi/ppapi_cdm_adapter.cc
@@ -107,11 +107,11 @@ return PP_DECRYPTRESULT_DECRYPT_ERROR; case cdm::kDecodeError: return PP_DECRYPTRESULT_DECODE_ERROR; - case cdm::kSessionError: + case cdm::kInitializationError: case cdm::kDeferredInitialization: - // kSessionError and kDeferredInitialization are only used by the - // Initialize* methods internally and never returned. Deliver* - // methods should never use these values. + // kInitializationError and kDeferredInitialization are only used by the + // Initialize* methods internally and never returned. Deliver* methods + // should never use these values. break; } @@ -255,26 +255,41 @@ return cdm::kKeyIds; } -PP_CdmExceptionCode CdmExceptionTypeToPpCdmExceptionType(cdm::Error error) { - switch (error) { - case cdm::kNotSupportedError: +PP_CdmExceptionCode CdmExceptionTypeToPpCdmExceptionType( + cdm::Exception exception) { + switch (exception) { + case cdm::Exception::kExceptionNotSupportedError: return PP_CDMEXCEPTIONCODE_NOTSUPPORTEDERROR; - case cdm::kInvalidStateError: + case cdm::Exception::kExceptionInvalidStateError: return PP_CDMEXCEPTIONCODE_INVALIDSTATEERROR; - case cdm::kInvalidAccessError: + case cdm::Exception::kExceptionTypeError: return PP_CDMEXCEPTIONCODE_INVALIDACCESSERROR; - case cdm::kQuotaExceededError: + case cdm::Exception::kExceptionQuotaExceededError: return PP_CDMEXCEPTIONCODE_QUOTAEXCEEDEDERROR; - case cdm::kUnknownError: - return PP_CDMEXCEPTIONCODE_UNKNOWNERROR; - case cdm::kClientError: - return PP_CDMEXCEPTIONCODE_CLIENTERROR; - case cdm::kOutputError: - return PP_CDMEXCEPTIONCODE_OUTPUTERROR; } PP_NOTREACHED(); - return PP_CDMEXCEPTIONCODE_UNKNOWNERROR; + return PP_CDMEXCEPTIONCODE_INVALIDSTATEERROR; +} + +cdm::Exception CdmErrorTypeToCdmExceptionType(cdm::Error error) { + switch (error) { + case cdm::kNotSupportedError: + return cdm::Exception::kExceptionNotSupportedError; + case cdm::kInvalidStateError: + return cdm::Exception::kExceptionInvalidStateError; + case cdm::kInvalidAccessError: + return cdm::Exception::kExceptionTypeError; + case cdm::kQuotaExceededError: + return cdm::Exception::kExceptionQuotaExceededError; + case cdm::kUnknownError: + case cdm::kClientError: + case cdm::kOutputError: + break; + } + + PP_NOTREACHED(); + return cdm::Exception::kExceptionInvalidStateError; } PP_CdmMessageType CdmMessageTypeToPpMessageType(cdm::MessageType message) { @@ -380,7 +395,7 @@ PP_URLComponents_Dev url_components = {}; const pp::URLUtil_Dev* url_util = pp::URLUtil_Dev::Get(); if (!url_util) { - RejectPromise(promise_id, cdm::kUnknownError, 0, + RejectPromise(promise_id, cdm::Exception::kExceptionInvalidStateError, 0, "Unable to determine origin."); return; } @@ -401,7 +416,7 @@ cdm_ = make_linked_ptr(CreateCdmInstance(key_system)); if (!cdm_) { - RejectPromise(promise_id, cdm::kInvalidAccessError, 0, + RejectPromise(promise_id, cdm::Exception::kExceptionInvalidStateError, 0, "Unable to create CDM."); return; } @@ -423,7 +438,7 @@ if (!server_certificate_ptr || server_certificate_size < media::limits::kMinCertificateLength || server_certificate_size > media::limits::kMaxCertificateLength) { - RejectPromise(promise_id, cdm::kInvalidAccessError, 0, + RejectPromise(promise_id, cdm::Exception::kExceptionTypeError, 0, "Incorrect certificate."); return; } @@ -509,7 +524,7 @@ pp::Buffer_Dev extra_data_buffer) { PP_DCHECK(!deferred_initialize_audio_decoder_); PP_DCHECK(deferred_audio_decoder_config_id_ == 0); - cdm::Status status = cdm::kSessionError; + cdm::Status status = cdm::kInitializationError; if (cdm_) { cdm::AudioDecoderConfig cdm_decoder_config; cdm_decoder_config.codec = @@ -539,7 +554,7 @@ pp::Buffer_Dev extra_data_buffer) { PP_DCHECK(!deferred_initialize_video_decoder_); PP_DCHECK(deferred_video_decoder_config_id_ == 0); - cdm::Status status = cdm::kSessionError; + cdm::Status status = cdm::kInitializationError; if (cdm_) { cdm::VideoDecoderConfig cdm_decoder_config; cdm_decoder_config.codec = @@ -658,6 +673,14 @@ return pp::Module::Get()->core()->GetTime(); } +void PpapiCdmAdapter::OnResolveKeyStatusPromise(uint32_t promise_id, + cdm::KeyStatus key_status) { + // TODO(xhwang): Implement HDCP Policy Check. https://crbug.com/709348. + PP_NOTREACHED(); + RejectPromise(promise_id, cdm::Exception::kExceptionNotSupportedError, 0, + "HDCP Policy Check not implemented."); +} + void PpapiCdmAdapter::OnResolveNewSessionPromise(uint32_t promise_id, const char* session_id, uint32_t session_id_size) { @@ -672,7 +695,7 @@ } void PpapiCdmAdapter::OnRejectPromise(uint32_t promise_id, - cdm::Error error, + cdm::Exception exception, uint32_t system_code, const char* error_message, uint32_t error_message_size) { @@ -685,17 +708,37 @@ kSizeKBMax, kSizeKBBuckets); } - RejectPromise(promise_id, error, system_code, + RejectPromise(promise_id, exception, system_code, std::string(error_message, error_message_size)); } +void PpapiCdmAdapter::OnRejectPromise(uint32_t promise_id, + cdm::Error error, + uint32_t system_code, + const char* error_message, + uint32_t error_message_size) { + OnRejectPromise(promise_id, CdmErrorTypeToCdmExceptionType(error), + system_code, error_message, error_message_size); +} + void PpapiCdmAdapter::RejectPromise(uint32_t promise_id, - cdm::Error error, + cdm::Exception exception, uint32_t system_code, const std::string& error_message) { PostOnMain(callback_factory_.NewCallback( &PpapiCdmAdapter::SendPromiseRejectedInternal, promise_id, - SessionError(error, system_code, error_message))); + SessionError(exception, system_code, error_message))); +} + +void PpapiCdmAdapter::OnSessionMessage(const char* session_id, + uint32_t session_id_size, + cdm::MessageType message_type, + const char* message, + uint32_t message_size) { + PostOnMain(callback_factory_.NewCallback( + &PpapiCdmAdapter::SendSessionMessageInternal, + SessionMessage(std::string(session_id, session_id_size), message_type, + message, message_size))); } void PpapiCdmAdapter::OnSessionMessage(const char* session_id, @@ -710,11 +753,8 @@ // License requests should not specify |legacy_destination_url|. PP_DCHECK(legacy_destination_url_size == 0 || message_type != cdm::MessageType::kLicenseRequest); - - PostOnMain(callback_factory_.NewCallback( - &PpapiCdmAdapter::SendSessionMessageInternal, - SessionMessage(std::string(session_id, session_id_size), message_type, - message, message_size))); + OnSessionMessage(session_id, session_id_size, message_type, message, + message_size); } void PpapiCdmAdapter::OnSessionKeysChange(const char* session_id, @@ -794,7 +834,7 @@ const SessionError& error) { PP_DCHECK(result == PP_OK); pp::ContentDecryptor_Private::PromiseRejected( - promise_id, CdmExceptionTypeToPpCdmExceptionType(error.error), + promise_id, CdmExceptionTypeToPpCdmExceptionType(error.exception), error.system_code, error.error_description); } @@ -1117,6 +1157,12 @@ } } +void PpapiCdmAdapter::RequestStorageId() { + // TODO(jrummell): Implement Storage Id. https://crbug.com/478960. + PP_NOTREACHED(); + cdm_->OnStorageId(nullptr, 0); +} + // The CDM owns the returned object and must call FileIO::Close() to release it. cdm::FileIO* PpapiCdmAdapter::CreateFileIO(cdm::FileIOClient* client) { if (!allow_persistent_state_) { @@ -1232,10 +1278,10 @@ } PpapiCdmAdapter::SessionError::SessionError( - cdm::Error error, + cdm::Exception exception, uint32_t system_code, const std::string& error_description) - : error(error), + : exception(exception), system_code(system_code), error_description(error_description) {} @@ -1252,7 +1298,7 @@ return NULL; static_assert( - cdm::ContentDecryptionModule::Host::kVersion == cdm::Host_8::kVersion, + cdm::ContentDecryptionModule::Host::kVersion == cdm::Host_9::kVersion, "update the code below"); // Ensure IsSupportedCdmHostVersion matches implementation of this function. @@ -1262,10 +1308,11 @@ PP_DCHECK( // Future version is not supported. - !IsSupportedCdmHostVersion(cdm::Host_8::kVersion + 1) && + !IsSupportedCdmHostVersion(cdm::Host_9::kVersion + 1) && // Current version is supported. - IsSupportedCdmHostVersion(cdm::Host_8::kVersion) && + IsSupportedCdmHostVersion(cdm::Host_9::kVersion) && // Include all previous supported versions (if any) here. + IsSupportedCdmHostVersion(cdm::Host_8::kVersion) && // One older than the oldest supported version is not supported. !IsSupportedCdmHostVersion(cdm::Host_8::kVersion - 1)); PP_DCHECK(IsSupportedCdmHostVersion(host_interface_version)); @@ -1275,6 +1322,8 @@ switch (host_interface_version) { case cdm::Host_8::kVersion: return static_cast<cdm::Host_8*>(cdm_adapter); + case cdm::Host_9::kVersion: + return static_cast<cdm::Host_9*>(cdm_adapter); default: PP_NOTREACHED(); return NULL;
diff --git a/media/cdm/ppapi/ppapi_cdm_adapter.h b/media/cdm/ppapi/ppapi_cdm_adapter.h index bd83aa3..91ddf97 100644 --- a/media/cdm/ppapi/ppapi_cdm_adapter.h +++ b/media/cdm/ppapi/ppapi_cdm_adapter.h
@@ -35,7 +35,8 @@ // Content Decryption Module (CDM). class PpapiCdmAdapter : public pp::Instance, public pp::ContentDecryptor_Private, - public cdm::Host_8 { + public cdm::Host_8, + public cdm::Host_9 { public: PpapiCdmAdapter(PP_Instance instance, pp::Module* module); virtual ~PpapiCdmAdapter(); @@ -82,16 +83,18 @@ pp::Buffer_Dev encrypted_buffer, const PP_EncryptedBlockInfo& encrypted_block_info) override; - // cdm::Host_8 implementation. + // cdm::Host_9 implementation. cdm::Buffer* Allocate(uint32_t capacity) override; void SetTimer(int64_t delay_ms, void* context) override; cdm::Time GetCurrentWallTime() override; + void OnResolveKeyStatusPromise(uint32_t promise_id, + cdm::KeyStatus key_status) override; void OnResolveNewSessionPromise(uint32_t promise_id, const char* session_id, uint32_t session_id_size) override; void OnResolvePromise(uint32_t promise_id) override; void OnRejectPromise(uint32_t promise_id, - cdm::Error error, + cdm::Exception exception, uint32_t system_code, const char* error_message, uint32_t error_message_size) override; @@ -99,9 +102,7 @@ uint32_t session_id_size, cdm::MessageType message_type, const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_size) override; + uint32_t message_size) override; void OnSessionKeysChange(const char* session_id, uint32_t session_id_size, bool has_additional_usable_key, @@ -112,12 +113,6 @@ cdm::Time new_expiry_time) override; void OnSessionClosed(const char* session_id, uint32_t session_id_size) override; - void OnLegacySessionError(const char* session_id, - uint32_t session_id_size, - cdm::Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) override; void SendPlatformChallenge(const char* service_id, uint32_t service_id_size, const char* challenge, @@ -126,8 +121,29 @@ void QueryOutputProtectionStatus() override; void OnDeferredInitializationDone(cdm::StreamType stream_type, cdm::Status decoder_status) override; + void RequestStorageId() override; cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) override; + // cdm::Host_8 implementation (differences from Host_9). + void OnSessionMessage(const char* session_id, + uint32_t session_id_size, + cdm::MessageType message_type, + const char* message, + uint32_t message_size, + const char* legacy_destination_url, + uint32_t legacy_destination_url_size) override; + void OnRejectPromise(uint32_t promise_id, + cdm::Error error, + uint32_t system_code, + const char* error_message, + uint32_t error_message_size) override; + void OnLegacySessionError(const char* session_id, + uint32_t session_id_size, + cdm::Error error, + uint32_t system_code, + const char* error_message, + uint32_t error_message_size) override; + private: // These are reported to UMA server. Do not change the existing values! enum OutputProtectionStatus { @@ -142,10 +158,10 @@ typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames; struct SessionError { - SessionError(cdm::Error error, + SessionError(cdm::Exception exception, uint32_t system_code, const std::string& error_description); - cdm::Error error; + cdm::Exception exception; uint32_t system_code; std::string error_description; }; @@ -187,7 +203,7 @@ const std::string& session_id, cdm::Time new_expiry_time); void RejectPromise(uint32_t promise_id, - cdm::Error error, + cdm::Exception exception, uint32_t system_code, const std::string& error_message);
diff --git a/media/cdm/supported_cdm_versions.cc b/media/cdm/supported_cdm_versions.cc index 281ca7e..fe9b161 100644 --- a/media/cdm/supported_cdm_versions.cc +++ b/media/cdm/supported_cdm_versions.cc
@@ -20,10 +20,11 @@ bool IsSupportedCdmInterfaceVersion(int version) { static_assert(cdm::ContentDecryptionModule::kVersion == - cdm::ContentDecryptionModule_8::kVersion, + cdm::ContentDecryptionModule_9::kVersion, "update the code below"); switch (version) { // Supported versions in decreasing order. + case cdm::ContentDecryptionModule_9::kVersion: case cdm::ContentDecryptionModule_8::kVersion: return true; default: @@ -33,10 +34,11 @@ bool IsSupportedCdmHostVersion(int version) { static_assert(cdm::ContentDecryptionModule::Host::kVersion == - cdm::ContentDecryptionModule_8::Host::kVersion, + cdm::ContentDecryptionModule_9::Host::kVersion, "update the code below"); switch (version) { // Supported versions in decreasing order. + case cdm::Host_9::kVersion: case cdm::Host_8::kVersion: return true; default:
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 1e5b1d0..6066206a 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -128,6 +128,7 @@ defines = [ "MEDIA_GPU_IMPLEMENTATION" ] sources = [ + "accelerated_video_decoder.h", "fake_jpeg_decode_accelerator.cc", "fake_jpeg_decode_accelerator.h", "fake_video_decode_accelerator.cc", @@ -139,6 +140,10 @@ "gpu_video_decode_accelerator_helpers.h", "gpu_video_encode_accelerator_factory.cc", "gpu_video_encode_accelerator_factory.h", + "h264_decoder.cc", + "h264_decoder.h", + "h264_dpb.cc", + "h264_dpb.h", "shared_memory_region.cc", "shared_memory_region.h", ] @@ -242,15 +247,6 @@ } } - if (is_chromeos || is_win) { - sources += [ - "accelerated_video_decoder.h", - "h264_decoder.cc", - "h264_decoder.h", - "h264_dpb.cc", - "h264_dpb.h", - ] - } if (is_chromeos) { sources += [ "vp8_decoder.cc", @@ -565,6 +561,20 @@ } } +source_set("unit_tests") { + testonly = true + deps = [ + "//base", + "//media/base:test_support", + "//media/gpu", + "//testing/gmock", + "//testing/gtest", + ] + sources = [ + "h264_decoder_unittest.cc", + ] +} + test("video_decode_accelerator_service_unittest") { sources = [ "ipc/service/gpu_jpeg_decode_accelerator_unittest.cc",
diff --git a/media/gpu/h264_decoder_unittest.cc b/media/gpu/h264_decoder_unittest.cc new file mode 100644 index 0000000..fdd01f37 --- /dev/null +++ b/media/gpu/h264_decoder_unittest.cc
@@ -0,0 +1,332 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> +#include <string.h> + +#include <memory> +#include <queue> +#include <string> + +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "media/base/test_data_util.h" +#include "media/gpu/h264_decoder.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::Expectation; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MakeMatcher; +using ::testing::Matcher; +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; +using ::testing::Mock; +using ::testing::Return; + +namespace media { +namespace { + +const std::string kBaselineFrame0 = "bear-320x192-baseline-frame-0.h264"; +const std::string kBaselineFrame1 = "bear-320x192-baseline-frame-1.h264"; +const std::string kBaselineFrame2 = "bear-320x192-baseline-frame-2.h264"; +const std::string kBaselineFrame3 = "bear-320x192-baseline-frame-3.h264"; +const std::string kHighFrame0 = "bear-320x192-high-frame-0.h264"; +const std::string kHighFrame1 = "bear-320x192-high-frame-1.h264"; +const std::string kHighFrame2 = "bear-320x192-high-frame-2.h264"; +const std::string kHighFrame3 = "bear-320x192-high-frame-3.h264"; + +class MockH264Accelerator : public H264Decoder::H264Accelerator { + public: + MockH264Accelerator() {} + + MOCK_METHOD0(CreateH264Picture, scoped_refptr<H264Picture>()); + MOCK_METHOD1(SubmitDecode, bool(const scoped_refptr<H264Picture>& pic)); + MOCK_METHOD1(OutputPicture, bool(const scoped_refptr<H264Picture>& pic)); + + bool SubmitFrameMetadata(const H264SPS* sps, + const H264PPS* pps, + const H264DPB& dpb, + const H264Picture::Vector& ref_pic_listp0, + const H264Picture::Vector& ref_pic_listb0, + const H264Picture::Vector& ref_pic_listb1, + const scoped_refptr<H264Picture>& pic) override { + return true; + } + + bool SubmitSlice(const H264PPS* pps, + const H264SliceHeader* slice_hdr, + const H264Picture::Vector& ref_pic_list0, + const H264Picture::Vector& ref_pic_list1, + const scoped_refptr<H264Picture>& pic, + const uint8_t* data, + size_t size) override { + return true; + } + + void Reset() override {} +}; + +// Test H264Decoder by feeding different of h264 frame sequences and make +// sure it behaves as expected. +class H264DecoderTest : public ::testing::Test { + public: + H264DecoderTest() = default; + + void SetUp() override; + + // Sets the bitstreams to be decoded, frame by frame. The content of each + // file is the encoded bitstream of a single video frame. + void SetInputFrameFiles(const std::vector<std::string>& frame_files); + + // Keeps decoding the input bitstream set at |SetInputFrameFiles| until the + // decoder has consumed all bitstreams or returned from + // |H264Decoder::Decode|. Returns the same result as |H264Decoder::Decode|. + AcceleratedVideoDecoder::DecodeResult Decode(); + + protected: + std::unique_ptr<H264Decoder> decoder_; + MockH264Accelerator accelerator_; + + private: + std::queue<std::string> input_frame_files_; + std::string bitstream_; +}; + +void H264DecoderTest::SetUp() { + decoder_.reset(new H264Decoder(&accelerator_)); + + // Sets default behaviors for mock methods for convenience. + ON_CALL(accelerator_, CreateH264Picture()).WillByDefault(Invoke([]() { + return new H264Picture(); + })); + ON_CALL(accelerator_, SubmitDecode(_)).WillByDefault(Return(true)); + ON_CALL(accelerator_, OutputPicture(_)).WillByDefault(Return(true)); +} + +void H264DecoderTest::SetInputFrameFiles( + const std::vector<std::string>& input_frame_files) { + for (auto f : input_frame_files) + input_frame_files_.push(f); +} + +AcceleratedVideoDecoder::DecodeResult H264DecoderTest::Decode() { + while (true) { + auto result = decoder_->Decode(); + if (result != AcceleratedVideoDecoder::kRanOutOfStreamData || + input_frame_files_.empty()) + return result; + auto input_file = GetTestDataFilePath(input_frame_files_.front()); + input_frame_files_.pop(); + CHECK(base::ReadFileToString(input_file, &bitstream_)); + decoder_->SetStream(reinterpret_cast<const uint8_t*>(bitstream_.data()), + bitstream_.size()); + } +} + +// To have better description on mismatch. +class WithPocMatcher + : public MatcherInterface<const scoped_refptr<H264Picture>&> { + public: + explicit WithPocMatcher(int expected_poc) : expected_poc_(expected_poc) {} + + bool MatchAndExplain(const scoped_refptr<H264Picture>& p, + MatchResultListener* listener) const override { + if (p->pic_order_cnt == expected_poc_) + return true; + *listener << "with poc: " << p->pic_order_cnt; + return false; + } + + void DescribeTo(std::ostream* os) const override { + *os << "with poc " << expected_poc_; + } + + private: + int expected_poc_; +}; + +inline Matcher<const scoped_refptr<H264Picture>&> WithPoc(int expected_poc) { + return MakeMatcher(new WithPocMatcher(expected_poc)); +} + +// Test Cases + +TEST_F(H264DecoderTest, DecodeSingleFrame) { + SetInputFrameFiles({kBaselineFrame0}); + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures()); + + EXPECT_CALL(accelerator_, CreateH264Picture()).WillOnce(Return(nullptr)); + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfSurfaces, Decode()); + ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_)); + + { + InSequence sequence; + EXPECT_CALL(accelerator_, CreateH264Picture()); + EXPECT_CALL(accelerator_, SubmitDecode(_)); + EXPECT_CALL(accelerator_, OutputPicture(_)); + } + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); + ASSERT_TRUE(decoder_->Flush()); +} + +TEST_F(H264DecoderTest, SkipNonIDRFrames) { + SetInputFrameFiles({kBaselineFrame1, kBaselineFrame2, kBaselineFrame0}); + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures()); + { + InSequence sequence; + EXPECT_CALL(accelerator_, CreateH264Picture()); + EXPECT_CALL(accelerator_, SubmitDecode(_)); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))); + } + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); + ASSERT_TRUE(decoder_->Flush()); +} + +TEST_F(H264DecoderTest, DecodeProfileBaseline) { + SetInputFrameFiles({ + kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, kBaselineFrame3, + }); + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures()); + + EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4); + Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6; + { + InSequence decode_order; + decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0))); + decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2))); + decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4))); + decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6))); + } + { + InSequence display_order; + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6); + } + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); + ASSERT_TRUE(decoder_->Flush()); +} + +TEST_F(H264DecoderTest, DecodeProfileHigh) { + SetInputFrameFiles({kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3}); + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures()); + + // Two pictures will be kept in DPB for reordering. The first picture should + // be outputted after feeding the third frame. + EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4); + Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6; + { + InSequence decode_order; + decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0))); + decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4))); + decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2))); + decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6))); + } + { + InSequence display_order; + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6); + } + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); + ASSERT_TRUE(decoder_->Flush()); +} + +TEST_F(H264DecoderTest, SwitchBaselineToHigh) { + SetInputFrameFiles({ + kBaselineFrame0, kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3, + }); + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures()); + + EXPECT_CALL(accelerator_, CreateH264Picture()); + { + InSequence sequence; + EXPECT_CALL(accelerator_, SubmitDecode(_)); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))); + } + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures()); + + ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_)); + + EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4); + Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6; + { + InSequence decode_order; + decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0))); + decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4))); + decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2))); + decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6))); + } + { + InSequence display_order; + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6); + } + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); + ASSERT_TRUE(decoder_->Flush()); +} + +TEST_F(H264DecoderTest, SwitchHighToBaseline) { + SetInputFrameFiles({ + kHighFrame0, kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, + kBaselineFrame3, + }); + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures()); + + EXPECT_CALL(accelerator_, CreateH264Picture()); + { + InSequence sequence; + EXPECT_CALL(accelerator_, SubmitDecode(_)); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))); + } + ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); + EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); + EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures()); + + ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_)); + + EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4); + Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6; + { + InSequence decode_order; + decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0))); + decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2))); + decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4))); + decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6))); + } + { + InSequence display_order; + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4); + EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6); + } + ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); + ASSERT_TRUE(decoder_->Flush()); +} + +} // namespace +} // namespace media
diff --git a/media/gpu/h264_dpb.h b/media/gpu/h264_dpb.h index e8f119f..2af8a77 100644 --- a/media/gpu/h264_dpb.h +++ b/media/gpu/h264_dpb.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "media/filters/h264_parser.h" +#include "media/gpu/media_gpu_export.h" #include "ui/gfx/geometry/rect.h" namespace media { @@ -24,7 +25,7 @@ // A picture (a frame or a field) in the H.264 spec sense. // See spec at http://www.itu.int/rec/T-REC-H.264 -class H264Picture : public base::RefCounted<H264Picture> { +class MEDIA_GPU_EXPORT H264Picture : public base::RefCounted<H264Picture> { public: using Vector = std::vector<scoped_refptr<H264Picture>>;
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn index 0d98b3c..9055e38e 100644 --- a/media/mojo/interfaces/BUILD.gn +++ b/media/mojo/interfaces/BUILD.gn
@@ -52,10 +52,36 @@ ] } +mojom("remoting_common") { + sources = [ + "remoting_common.mojom", + ] + + # TODO(crbug.com/699569): Convert to use the new JS bindings. + use_new_js_bindings = false +} + +mojom("mirror_service_remoting") { + sources = [ + "mirror_service_remoting.mojom", + ] + + public_deps = [ + ":remoting_common", + ] + + # TODO(crbug.com/699569): Convert to use the new JS bindings. + use_new_js_bindings = false +} + mojom("remoting") { sources = [ "remoting.mojom", ] + + public_deps = [ + ":remoting_common", + ] } mojom("test_interfaces") {
diff --git a/media/mojo/interfaces/mirror_service_remoting.mojom b/media/mojo/interfaces/mirror_service_remoting.mojom new file mode 100644 index 0000000..0c76dbb --- /dev/null +++ b/media/mojo/interfaces/mirror_service_remoting.mojom
@@ -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. + +module media.mojom; + +import "media/mojo/interfaces/remoting_common.mojom"; + +// Interface used by the source to start/stop remoting and send data to the +// sink. +interface MirrorServiceRemoter { + // Starts a remoting session. Always assumes the remoting session will be + // stared successfully. If any failure happens, + // MirrorServiceRemotingSource::OnError() will be called. + Start(); + + // Starts remoting the media data streams. This is called after Start() to + // indicate audio/video bitstream data is ready to be consumed. Returns + // audio/video stream IDs. A valid stream ID should be greater than 0. When + // there is no audio/video, or if the data stream is not successfully started, + // the returned stream ID is -1. + StartDataStreams(bool has_audio, bool has_video) + => (int32 audio_stream_id, int32 video_stream_id); + + // Stops remoting media. Messages in both directions will be dropped after + // this point as well as any pending or in-transit media bitstream data. + Stop(RemotingStopReason reason); + + // Sends|message| to the sink. |message| is a serialized protobuf from + // src/media/remoting/proto. + SendMessageToSink(array<uint8> message); +}; + +// Interface used for sending notifications back to the source's control logic, +// and to pass messages from the sink back to the source. +interface MirrorServiceRemotingSource { + // Notifies the source that the sink is now available to start remoting and + // passes the receiver's capabilities. It is up to the source's control logic + // to decide whether/when to start remoting. + OnSinkAvailable(SinkCapabilities capabilities); + + // Passes a |message| from the sink back to the source. The |message| consists + // of a serialized protobuf from src/media/remoting/proto. This will only be + // called after OnStarted() and before OnStopped(). + OnMessageFromSink(array<uint8> message); + + // Notifies the source that remoting has terminated. This may or may not be in + // response to a MirrorServiceRemoter.Stop() call, as other events (possibly + // external) may have caused remoting to end. + OnStopped(RemotingStopReason reason); + + // Notifies the source that a fatal error has occurred. Remoting session will + // be stopped immediately once this is called. + // TODO(xjz): Add error codes in future to indicate different errors. + OnError(); +};
diff --git a/media/mojo/interfaces/remoting.mojom b/media/mojo/interfaces/remoting.mojom index ba218f3..8960cb4 100644 --- a/media/mojo/interfaces/remoting.mojom +++ b/media/mojo/interfaces/remoting.mojom
@@ -4,6 +4,8 @@ module media.mojom; +import "media/mojo/interfaces/remoting_common.mojom"; + interface RemoterFactory { // Create a new Remoter associated with the given RemotingSource and bind it // to the given interface request. The RemotingSource will be notified when @@ -32,7 +34,7 @@ // provide all of the frame's data. SendFrame(); - // Cancel the transmission of all in-flight data to the remote, up to and + // Cancels the transmission of all in-flight data to the remote, up to and // including the last SendFrame() call; and also discard any data chunks // that were consumed from the data pipe for the next frame. This is used to // optimize seeking, when it is known that any in-flight data is no longer @@ -41,26 +43,17 @@ CancelInFlightData(); }; -enum RemotingStopReason { - ROUTE_TERMINATED, // User-initiated disconnect, etc. - LOCAL_PLAYBACK, // Media switched back to local playback. - SOURCE_GONE, // RemotingSource has been destroyed. - MESSAGE_SEND_FAILED, // Failed to send a message to the sink. - DATA_SEND_FAILED, // Failed to consume from a data pipe or send to the sink. - UNEXPECTED_FAILURE, // Unexpected failure or inconsistent state encountered. -}; - // Interface used by the source to start/stop remoting and send data to the // sink. interface Remoter { - // Start a remoting session (once the sink has been reported to be available; + // Starts a remoting session (once the sink has been reported to be available; // see RemotingSource). Either RemotingSource.OnStarted() or OnStartFailed() // will be called to indicate success or failure. Once OnStarted() has been // invoked, the source may then make calls to SendMessageToSink() and expect // messages from the remote via RemotingSource.OnMessageFromSink(). Start(); - // Start remoting the media data streams. This is called after Start() to + // Starts remoting the media data streams. This is called after Start() to // provide data pipes from which the audio/video bitstream data is consumed // and then transported to the remote device. RemotingDataStreamSenders are // used by the source to control when data should be consumed from the data @@ -71,37 +64,34 @@ RemotingDataStreamSender&? audio_sender, RemotingDataStreamSender&? video_sender); - // Stop remoting media. Messages in both directions will be dropped after this + // Stops remoting media. Messages in both directions will be dropped after this // point as well as any pending or in-transit media bitstream data. Stop(RemotingStopReason reason); - // Send |message| to the sink. |message| is a serialized protobuf from + // Sends |message| to the sink. |message| is a serialized protobuf from // src/media/remoting/proto. SendMessageToSink(array<uint8> message); }; +// TODO(xjz): Replace this with the SinkCapabilities struct defined in +// remoting_common.mojom. enum RemotingSinkCapabilities { NONE, RENDERING_ONLY, CONTENT_DECRYPTION_AND_RENDERING, }; -enum RemotingStartFailReason { - CANNOT_START_MULTIPLE, // Remoting was already active. - ROUTE_TERMINATED, // User-initated disconnect while starting remoting. -}; - // Interface used for sending notifications back to the local source's control // logic, and to pass messages from the sink back to the local media pipeline. interface RemotingSource { - // Notify the source that the sink is now available to start remoting. It is + // Notifies the source that the sink is now available to start remoting. It is // up to the source's control logic to decide whether/when to start remoting. // // TODO(miu): In a later change, pass detailed information about the sink's // capabilities (e.g., codec support, DRM keysystem support, etc.). OnSinkAvailable(RemotingSinkCapabilities capabilities); - // Notify the source that the sink is no longer available for remoting. This + // Notifies the source that the sink is no longer available for remoting. This // may happen, for example, because the sink has been shut down, or because // another source has started remoting. OnSinkGone(); @@ -114,12 +104,12 @@ OnStarted(); OnStartFailed(RemotingStartFailReason reason); - // Pass a |message| from the sink back to the source. The |message| consists + // Passes a |message| from the sink back to the source. The |message| consists // of a serialized protobuf from src/media/remoting/proto. This will only be // called after OnStarted() and before OnStopped(). OnMessageFromSink(array<uint8> message); - // Notify the source that remoting has terminated. This may or may not be in + // Notifies the source that remoting has terminated. This may or may not be in // response to a Remoter.Stop() call, as other events (possibly external) may // have caused remoting to end. OnStopped(RemotingStopReason reason);
diff --git a/media/mojo/interfaces/remoting_common.mojom b/media/mojo/interfaces/remoting_common.mojom new file mode 100644 index 0000000..fe3536e --- /dev/null +++ b/media/mojo/interfaces/remoting_common.mojom
@@ -0,0 +1,47 @@ +// 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. + +module media.mojom; + +enum RemotingStopReason { + ROUTE_TERMINATED, // User-initiated disconnect, etc. + LOCAL_PLAYBACK, // Media switched back to local playback. + SOURCE_GONE, // RemotingSource has been destroyed. + MESSAGE_SEND_FAILED, // Failed to send a message to the sink. + DATA_SEND_FAILED, // Failed to consume from a data pipe or send to the sink. + UNEXPECTED_FAILURE, // Unexpected failure or inconsistent state encountered. + SERVICE_GONE, // Mirror service disconnected. +}; + +enum RemotingStartFailReason { + CANNOT_START_MULTIPLE, // Remoting was already active. + ROUTE_TERMINATED, // User-initated disconnect while starting remoting. + SERVICE_NOT_CONNECTED, // Mirror service was not connected. +}; + +enum RemotingSinkFeatures { + RENDERING, + CONTENT_DECRYPTION, +}; + +enum RemotingSinkAudioCapabilities { + CODEC_BASELINE_SET, + CODEC_AAC, + CODEC_OPUS, +}; + +enum RemotingSinkVideoCapabilities { + SUPPORT_4K, + CODEC_BASELINE_SET, + CODEC_H264, + CODEC_VP8, + CODEC_VP9, + CODEC_HEVC, +}; + +struct SinkCapabilities { + array<RemotingSinkFeatures> features; + array<RemotingSinkAudioCapabilities> audio; + array<RemotingSinkVideoCapabilities> video; +};
diff --git a/media/remoting/proto_utils.cc b/media/remoting/proto_utils.cc index 55e1ab5..3920163 100644 --- a/media/remoting/proto_utils.cc +++ b/media/remoting/proto_utils.cc
@@ -11,6 +11,7 @@ #include "base/time/time.h" #include "base/values.h" #include "media/base/encryption_scheme.h" +#include "media/base/timestamp_constants.h" #include "media/remoting/proto_enum_utils.h" namespace media { @@ -346,6 +347,13 @@ // HACK: Set the following to prevent "disable video when hidden" logic in // media::blink::WebMediaPlayerImpl. stats->video_keyframe_distance_average = base::TimeDelta::Max(); + + // This field was added after the initial message definition. Check that + // sender provided the value. + if (stats_message.has_video_frame_duration_average_usec()) { + stats->video_frame_duration_average = base::TimeDelta::FromMicroseconds( + stats_message.video_frame_duration_average_usec()); + } } void ConvertCdmKeyInfoToProto(
diff --git a/media/remoting/proto_utils_unittest.cc b/media/remoting/proto_utils_unittest.cc index c974c0f8..12aae106 100644 --- a/media/remoting/proto_utils_unittest.cc +++ b/media/remoting/proto_utils_unittest.cc
@@ -142,6 +142,7 @@ original.audio_memory_usage = 32; original.video_memory_usage = 43; original.video_keyframe_distance_average = base::TimeDelta::Max(); + original.video_frame_duration_average = base::TimeDelta::Max(); // There is no convert-to-proto function, so just do that here. pb::PipelineStatistics pb_stats; @@ -151,6 +152,8 @@ pb_stats.set_video_frames_dropped(original.video_frames_dropped); pb_stats.set_audio_memory_usage(original.audio_memory_usage); pb_stats.set_video_memory_usage(original.video_memory_usage); + pb_stats.set_video_frame_duration_average_usec( + original.video_frame_duration_average.InMicroseconds()); PipelineStatistics converted; memset(&converted, ~0xcd, sizeof(converted)); // See note above.
diff --git a/media/remoting/renderer_controller.cc b/media/remoting/renderer_controller.cc index 998fa99..176c930 100644 --- a/media/remoting/renderer_controller.cc +++ b/media/remoting/renderer_controller.cc
@@ -118,6 +118,7 @@ } void RendererController::OnSetCdm(CdmContext* cdm_context) { + VLOG(2) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); auto* remoting_cdm_context = RemotingCdmContext::From(cdm_context); @@ -131,6 +132,7 @@ } void RendererController::OnRemotePlaybackDisabled(bool disabled) { + VLOG(2) << __func__ << ": disabled = " << disabled; DCHECK(thread_checker_.CalledOnValidThread()); is_remote_playback_disabled_ = disabled; @@ -290,6 +292,10 @@ case mojom::RemotingSinkCapabilities::RENDERING_ONLY: case mojom::RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING: break; // The sink is capable of remote rendering. + default: + // TODO(xjz): Will be changed in a coming CL that passes the receiver's + // capabilities. + NOTREACHED(); } if ((!has_audio() && !has_video()) || @@ -352,6 +358,7 @@ } void RendererController::OnRendererFatalError(StopTrigger stop_trigger) { + VLOG(2) << __func__ << ": stop_trigger= " << stop_trigger; DCHECK(thread_checker_.CalledOnValidThread()); // Do not act on errors caused by things like Mojo pipes being closed during
diff --git a/media/remoting/rpc.proto b/media/remoting/rpc.proto index f8f0cd6..aaab7b39 100644 --- a/media/remoting/rpc.proto +++ b/media/remoting/rpc.proto
@@ -254,6 +254,7 @@ optional uint32 video_frames_dropped = 4; optional int64 audio_memory_usage = 5; optional int64 video_memory_usage = 6; + optional int64 video_frame_duration_average_usec = 7; }; message CdmKeyInformation {
diff --git a/media/renderers/video_renderer_impl.cc b/media/renderers/video_renderer_impl.cc index fbd82d7b..5f3ada1d 100644 --- a/media/renderers/video_renderer_impl.cc +++ b/media/renderers/video_renderer_impl.cc
@@ -696,6 +696,9 @@ const size_t memory_usage = algorithm_->GetMemoryUsage(); statistics.video_memory_usage = memory_usage - last_video_memory_usage_; + statistics.video_frame_duration_average = + algorithm_->average_frame_duration(); + task_runner_->PostTask(FROM_HERE, base::Bind(&VideoRendererImpl::OnStatisticsUpdate, weak_factory_.GetWeakPtr(), statistics));
diff --git a/media/test/data/bear-320x192-baseline-frame-0.h264 b/media/test/data/bear-320x192-baseline-frame-0.h264 new file mode 100644 index 0000000..a8d6a14d --- /dev/null +++ b/media/test/data/bear-320x192-baseline-frame-0.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-baseline-frame-1.h264 b/media/test/data/bear-320x192-baseline-frame-1.h264 new file mode 100644 index 0000000..21176c4 --- /dev/null +++ b/media/test/data/bear-320x192-baseline-frame-1.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-baseline-frame-2.h264 b/media/test/data/bear-320x192-baseline-frame-2.h264 new file mode 100644 index 0000000..10c93782 --- /dev/null +++ b/media/test/data/bear-320x192-baseline-frame-2.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-baseline-frame-3.h264 b/media/test/data/bear-320x192-baseline-frame-3.h264 new file mode 100644 index 0000000..9e7e37f --- /dev/null +++ b/media/test/data/bear-320x192-baseline-frame-3.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-high-frame-0.h264 b/media/test/data/bear-320x192-high-frame-0.h264 new file mode 100644 index 0000000..1379b224c --- /dev/null +++ b/media/test/data/bear-320x192-high-frame-0.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-high-frame-1.h264 b/media/test/data/bear-320x192-high-frame-1.h264 new file mode 100644 index 0000000..b06a1dfa --- /dev/null +++ b/media/test/data/bear-320x192-high-frame-1.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-high-frame-2.h264 b/media/test/data/bear-320x192-high-frame-2.h264 new file mode 100644 index 0000000..36ccb65 --- /dev/null +++ b/media/test/data/bear-320x192-high-frame-2.h264 Binary files differ
diff --git a/media/test/data/bear-320x192-high-frame-3.h264 b/media/test/data/bear-320x192-high-frame-3.h264 new file mode 100644 index 0000000..a53c98f8 --- /dev/null +++ b/media/test/data/bear-320x192-high-frame-3.h264 Binary files differ
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 85b658e..d084a2397 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -1937,15 +1937,6 @@ static_assert(arraysize(kChangeCauseMapping) == DELETE_COOKIE_LAST_ENTRY + 1, "kChangeCauseMapping size should match DeletionCause size"); - // See InitializeHistograms() for details. - DeletionCause deletion_cause_to_record = deletion_cause; - if (deletion_cause >= DELETE_COOKIE_CREATED_BETWEEN && - deletion_cause <= DELETE_COOKIE_CANONICAL) { - deletion_cause_to_record = DELETE_COOKIE_EXPLICIT; - } - if (deletion_cause != DELETE_COOKIE_DONT_RECORD) - histogram_cookie_deletion_cause_->Add(deletion_cause_to_record); - CanonicalCookie* cc = it->second.get(); VLOG(kVlogSetCookies) << "InternalDeleteCookie()" << ", cause:" << deletion_cause @@ -2202,8 +2193,6 @@ DCHECK(thread_checker_.CalledOnValidThread()); for (CookieItVector::iterator it = it_begin; it != it_end; it++) { - histogram_evicted_last_access_minutes_->Add( - (current - (*it)->second->LastAccessDate()).InMinutes()); InternalDeleteCookie((*it), true, cause); } return it_end - it_begin; @@ -2348,16 +2337,10 @@ histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet( "Cookie.ExpirationDurationMinutes", 1, kMinutesInTenYears, 50, base::Histogram::kUmaTargetedHistogramFlag); - histogram_evicted_last_access_minutes_ = base::Histogram::FactoryGet( - "Cookie.EvictedLastAccessMinutes", 1, kMinutesInTenYears, 50, - base::Histogram::kUmaTargetedHistogramFlag); histogram_count_ = base::Histogram::FactoryGet( "Cookie.Count", 1, 4000, 50, base::Histogram::kUmaTargetedHistogramFlag); // From UMA_HISTOGRAM_ENUMERATION - histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet( - "Cookie.DeletionCause", 1, DELETE_COOKIE_LAST_ENTRY - 1, - DELETE_COOKIE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); histogram_cookie_type_ = base::LinearHistogram::FactoryGet( "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1, 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index 6d8a533..7fb91e44 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h
@@ -675,9 +675,7 @@ // Histogram variables; see CookieMonster::InitializeHistograms() in // cookie_monster.cc for details. base::HistogramBase* histogram_expiration_duration_minutes_; - base::HistogramBase* histogram_evicted_last_access_minutes_; base::HistogramBase* histogram_count_; - base::HistogramBase* histogram_cookie_deletion_cause_; base::HistogramBase* histogram_cookie_type_; base::HistogramBase* histogram_cookie_source_scheme_; base::HistogramBase* histogram_cookie_delete_equivalent_;
diff --git a/net/dns/dns_config_service.h b/net/dns/dns_config_service.h index d8845d1b..603fb4cc 100644 --- a/net/dns/dns_config_service.h +++ b/net/dns/dns_config_service.h
@@ -11,7 +11,6 @@ #include <vector> #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/timer/timer.h"
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 81fc5d5..fa86ecc 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -15,7 +15,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h"
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 9790f49..d961dde 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -19,7 +19,6 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "base/time/time.h"
diff --git a/net/ssl/default_channel_id_store.h b/net/ssl/default_channel_id_store.h index b07495c6e..bc5ab07 100644 --- a/net/ssl/default_channel_id_store.h +++ b/net/ssl/default_channel_id_store.h
@@ -14,7 +14,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "net/base/net_export.h" #include "net/ssl/channel_id_store.h"
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index c38dea98..5bd634c9 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -250,56 +250,6 @@ void SetSpdyAndQuicEnabled(bool spdy_enabled, bool quic_enabled); - void set_quic_connection_options( - const QuicTagVector& quic_connection_options) { - http_network_session_params_.quic_connection_options = - quic_connection_options; - } - - void set_quic_user_agent_id(const std::string& quic_user_agent_id) { - http_network_session_params_.quic_user_agent_id = quic_user_agent_id; - } - - void set_quic_max_server_configs_stored_in_properties( - int quic_max_server_configs_stored_in_properties) { - http_network_session_params_.quic_max_server_configs_stored_in_properties = - quic_max_server_configs_stored_in_properties; - } - - void set_quic_idle_connection_timeout_seconds( - int quic_idle_connection_timeout_seconds) { - http_network_session_params_.quic_idle_connection_timeout_seconds = - quic_idle_connection_timeout_seconds; - } - - void set_quic_close_sessions_on_ip_change( - bool quic_close_sessions_on_ip_change) { - http_network_session_params_.quic_close_sessions_on_ip_change = - quic_close_sessions_on_ip_change; - } - - void set_quic_migrate_sessions_on_network_change( - bool quic_migrate_sessions_on_network_change) { - http_network_session_params_.quic_migrate_sessions_on_network_change = - quic_migrate_sessions_on_network_change; - } - - void set_quic_migrate_sessions_early(bool quic_migrate_sessions_early) { - http_network_session_params_.quic_migrate_sessions_early = - quic_migrate_sessions_early; - } - - void set_quic_disable_bidirectional_streams( - bool quic_disable_bidirectional_streams) { - http_network_session_params_.quic_disable_bidirectional_streams = - quic_disable_bidirectional_streams; - } - - void set_quic_race_cert_verification(bool quic_race_cert_verification) { - http_network_session_params_.quic_race_cert_verification = - quic_race_cert_verification; - } - void set_throttling_enabled(bool throttling_enabled) { throttling_enabled_ = throttling_enabled; }
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 0c43ddcc..8007319 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -172,6 +172,7 @@ "host_session_options.h", "host_status_logger.cc", "host_status_logger.h", + "host_status_monitor.cc", "host_status_monitor.h", "host_status_observer.h", "host_window.cc", @@ -411,7 +412,6 @@ "fake_desktop_environment.h", "fake_host_extension.cc", "fake_host_extension.h", - "fake_host_status_monitor.h", "fake_mouse_cursor_monitor.cc", "fake_mouse_cursor_monitor.h", "host_mock_objects.cc",
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 3e2ce47..d165dd6 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc
@@ -75,7 +75,7 @@ transport_context_(transport_context), audio_task_runner_(audio_task_runner), video_encode_task_runner_(video_encode_task_runner), - started_(false), + status_monitor_(new HostStatusMonitor()), login_backoff_(&kDefaultBackoffPolicy), desktop_environment_options_(options), weak_factory_(this) { @@ -96,7 +96,7 @@ // Notify observers. if (started_) { - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnShutdown(); } } @@ -107,23 +107,13 @@ HOST_LOG << "Starting host"; started_ = true; - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnStart(host_owner_email); session_manager_->AcceptIncoming( base::Bind(&ChromotingHost::OnIncomingSession, base::Unretained(this))); } -void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - status_observers_.AddObserver(observer); -} - -void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - status_observers_.RemoveObserver(observer); -} - void ChromotingHost::AddExtension(std::unique_ptr<HostExtension> extension) { extensions_.push_back(std::move(extension)); } @@ -176,7 +166,7 @@ DCHECK(clients_.front().get() == client); // Notify observers that there is at least one authenticated client. - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnClientAuthenticated(client->client_jid()); } @@ -184,7 +174,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Notify observers. - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnClientConnected(client->client_jid()); } @@ -192,7 +182,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Notify observers. - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnAccessDenied(client->client_jid()); } @@ -211,7 +201,7 @@ clients_.erase(it); if (was_authenticated) { - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnClientDisconnected(jid); } } @@ -221,7 +211,7 @@ const std::string& channel_name, const protocol::TransportRoute& route) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (auto& observer : status_observers_) + for (auto& observer : status_monitor_->observers()) observer.OnClientRouteChange(session->client_jid(), channel_name, route); }
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 049c120..d907fa20 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h
@@ -62,8 +62,7 @@ // all pending tasks to complete. After all of that completed we // return to the idle state. We then go to step (2) if there a new // incoming connection. -class ChromotingHost : public ClientSession::EventHandler, - public HostStatusMonitor { +class ChromotingHost : public ClientSession::EventHandler { public: typedef std::vector<std::unique_ptr<ClientSession>> ClientSessions; @@ -85,9 +84,7 @@ // This method can only be called once during the lifetime of this object. void Start(const std::string& host_owner); - // HostStatusMonitor interface. - void AddStatusObserver(HostStatusObserver* observer) override; - void RemoveStatusObserver(HostStatusObserver* observer) override; + scoped_refptr<HostStatusMonitor> status_monitor() { return status_monitor_; } // Registers a host extension. void AddExtension(std::unique_ptr<HostExtension> extension); @@ -133,10 +130,6 @@ const ClientSessions& client_sessions_for_tests() { return clients_; } - base::WeakPtr<ChromotingHost> AsWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - scoped_refptr<protocol::TransportContext> transport_context_for_tests() { return transport_context_; } @@ -154,14 +147,13 @@ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner_; - // Must be used on the network thread only. - base::ObserverList<HostStatusObserver> status_observers_; + scoped_refptr<HostStatusMonitor> status_monitor_; // The connections to remote clients. ClientSessions clients_; // True if the host has been started. - bool started_; + bool started_ = false; // Login backoff state. net::BackoffEntry login_backoff_;
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index 5fc75e40..d8519e8 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc
@@ -70,10 +70,10 @@ host_.reset(new ChromotingHost( desktop_environment_factory_.get(), base::WrapUnique(session_manager_), protocol::TransportContext::ForTests(protocol::TransportRole::SERVER), - task_runner_, // Audio + task_runner_, // Audio task_runner_, DesktopEnvironmentOptions::CreateDefault())); // Video encode - host_->AddStatusObserver(&host_status_observer_); + host_->status_monitor()->AddStatusObserver(&host_status_observer_); xmpp_login_ = "host@domain"; session1_ = new MockSession();
diff --git a/remoting/host/daemon_process.cc b/remoting/host/daemon_process.cc index cc7ec8e..40b5c72 100644 --- a/remoting/host/daemon_process.cc +++ b/remoting/host/daemon_process.cc
@@ -46,10 +46,8 @@ DaemonProcess::~DaemonProcess() { DCHECK(caller_task_runner()->BelongsToCurrentThread()); - host_event_logger_.reset(); - weak_factory_.InvalidateWeakPtrs(); - - config_watcher_.reset(); + host_event_logger_ = nullptr; + config_watcher_ = nullptr; DeleteAllDesktopSessions(); } @@ -69,18 +67,6 @@ Stop(); } -void DaemonProcess::AddStatusObserver(HostStatusObserver* observer) { - DCHECK(caller_task_runner()->BelongsToCurrentThread()); - - status_observers_.AddObserver(observer); -} - -void DaemonProcess::RemoveStatusObserver(HostStatusObserver* observer) { - DCHECK(caller_task_runner()->BelongsToCurrentThread()); - - status_observers_.RemoveObserver(observer); -} - void DaemonProcess::OnChannelConnected(int32_t peer_pid) { DCHECK(caller_task_runner()->BelongsToCurrentThread()); @@ -191,8 +177,8 @@ io_task_runner_(io_task_runner), next_terminal_id_(0), stopped_callback_(stopped_callback), - current_process_stats_("DaemonProcess"), - weak_factory_(this) { + status_monitor_(new HostStatusMonitor()), + current_process_stats_("DaemonProcess") { DCHECK(caller_task_runner->BelongsToCurrentThread()); // TODO(sammc): On OSX, mojo::edk::SetMachPortProvider() should be called with // a base::PortProvider implementation. Add it here when this code is used on @@ -290,7 +276,7 @@ caller_task_runner(), io_task_runner(), config_path)); config_watcher_->Watch(this); host_event_logger_ = - HostEventLogger::Create(weak_factory_.GetWeakPtr(), kApplicationName); + HostEventLogger::Create(status_monitor_, kApplicationName); // Launch the process. LaunchNetworkProcess();
diff --git a/remoting/host/daemon_process.h b/remoting/host/daemon_process.h index 562b1a2d..8047f29 100644 --- a/remoting/host/daemon_process.h +++ b/remoting/host/daemon_process.h
@@ -14,7 +14,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/process/process.h" #include "base/time/time.h" @@ -46,7 +45,6 @@ // sessions. class DaemonProcess : public ConfigWatcher::Delegate, - public HostStatusMonitor, public WorkerProcessIpcDelegate, public protocol::ProcessStatsStub { public: @@ -67,9 +65,7 @@ void OnConfigUpdated(const std::string& serialized_config) override; void OnConfigWatcherError() override; - // HostStatusMonitor interface. - void AddStatusObserver(HostStatusObserver* observer) override; - void RemoveStatusObserver(HostStatusObserver* observer) override; + scoped_refptr<HostStatusMonitor> status_monitor() { return status_monitor_; } // WorkerProcessIpcDelegate implementation. void OnChannelConnected(int32_t peer_pid) override; @@ -201,6 +197,8 @@ // Writes host status updates to the system event log. std::unique_ptr<HostEventLogger> host_event_logger_; + scoped_refptr<HostStatusMonitor> status_monitor_; + // Reports process statistic data to network process. std::unique_ptr<ProcessStatsSender> stats_sender_; @@ -215,8 +213,6 @@ CurrentProcessStatsAgent current_process_stats_; - base::WeakPtrFactory<DaemonProcess> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(DaemonProcess); };
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc index 3b2ae57..6505892 100644 --- a/remoting/host/desktop_process.cc +++ b/remoting/host/desktop_process.cc
@@ -38,7 +38,8 @@ : caller_task_runner_(caller_task_runner), input_task_runner_(input_task_runner), io_task_runner_(io_task_runner), - daemon_channel_handle_(std::move(daemon_channel_handle)) { + daemon_channel_handle_(std::move(daemon_channel_handle)), + weak_factory_(this) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); DCHECK(base::MessageLoopForUI::IsCurrent()); } @@ -66,7 +67,7 @@ daemon_channel_->Send(new ChromotingDesktopDaemonMsg_InjectSas()); } -void DesktopProcess::LockWorkStation() { +void DesktopProcess::LockWorkstation() { DCHECK(caller_task_runner_->BelongsToCurrentThread()); #if defined(OS_WIN) if (base::win::OSInfo::GetInstance()->version_type() == @@ -145,7 +146,7 @@ // Start the agent and create an IPC channel to talk to it. mojo::ScopedMessagePipeHandle desktop_pipe = - desktop_agent_->Start(AsWeakPtr()); + desktop_agent_->Start(weak_factory_.GetWeakPtr()); // Connect to the daemon. daemon_channel_ = IPC::ChannelProxy::Create(daemon_channel_handle_.release(),
diff --git a/remoting/host/desktop_process.h b/remoting/host/desktop_process.h index 7454590..0c084e92 100644 --- a/remoting/host/desktop_process.h +++ b/remoting/host/desktop_process.h
@@ -30,8 +30,7 @@ class DesktopSessionAgent; class DesktopProcess : public DesktopSessionAgent::Delegate, - public IPC::Listener, - public base::SupportsWeakPtr<DesktopProcess> { + public IPC::Listener { public: DesktopProcess(scoped_refptr<AutoThreadTaskRunner> caller_task_runner, scoped_refptr<AutoThreadTaskRunner> input_task_runner, @@ -52,7 +51,7 @@ void InjectSas(); // Locks the workstation for the current session. - void LockWorkStation(); + void LockWorkstation(); // Creates the desktop agent and required threads and IPC channels. Returns // true on success. @@ -90,6 +89,8 @@ // the network process. scoped_refptr<DesktopSessionAgent> desktop_agent_; + base::WeakPtrFactory<DesktopProcess> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(DesktopProcess); };
diff --git a/remoting/host/desktop_process_main.cc b/remoting/host/desktop_process_main.cc index d898bd0..56c5f6f 100644 --- a/remoting/host/desktop_process_main.cc +++ b/remoting/host/desktop_process_main.cc
@@ -79,12 +79,15 @@ // Create a platform-dependent environment factory. std::unique_ptr<DesktopEnvironmentFactory> desktop_environment_factory; #if defined(OS_WIN) + // base::Unretained() is safe here: |desktop_process| outlives run_loop.Run(). + auto inject_sas_closure = base::Bind(&DesktopProcess::InjectSas, + base::Unretained(&desktop_process)); + auto lock_workstation_closure = base::Bind( + &DesktopProcess::LockWorkstation, base::Unretained(&desktop_process)); + desktop_environment_factory.reset(new SessionDesktopEnvironmentFactory( ui_task_runner, video_capture_task_runner, input_task_runner, - ui_task_runner, - base::Bind(&DesktopProcess::InjectSas, desktop_process.AsWeakPtr()), - base::Bind(&DesktopProcess::LockWorkStation, - desktop_process.AsWeakPtr()))); + ui_task_runner, inject_sas_closure, lock_workstation_closure)); #else // !defined(OS_WIN) desktop_environment_factory.reset(new Me2MeDesktopEnvironmentFactory( ui_task_runner, video_capture_task_runner, input_task_runner,
diff --git a/remoting/host/fake_desktop_environment.cc b/remoting/host/fake_desktop_environment.cc index 6597f96..6209c23 100644 --- a/remoting/host/fake_desktop_environment.cc +++ b/remoting/host/fake_desktop_environment.cc
@@ -15,7 +15,7 @@ namespace remoting { -FakeInputInjector::FakeInputInjector() {} +FakeInputInjector::FakeInputInjector() : weak_factory_(this) {} FakeInputInjector::~FakeInputInjector() {} void FakeInputInjector::Start( @@ -57,7 +57,9 @@ FakeDesktopEnvironment::FakeDesktopEnvironment( scoped_refptr<base::SingleThreadTaskRunner> capture_thread, const DesktopEnvironmentOptions& options) - : capture_thread_(std::move(capture_thread)), options_(options) {} + : capture_thread_(std::move(capture_thread)), + options_(options), + weak_factory_(this) {} FakeDesktopEnvironment::~FakeDesktopEnvironment() = default; @@ -68,7 +70,7 @@ std::unique_ptr<InputInjector> FakeDesktopEnvironment::CreateInputInjector() { std::unique_ptr<FakeInputInjector> result(new FakeInputInjector()); - last_input_injector_ = result->AsWeakPtr(); + last_input_injector_ = result->weak_factory_.GetWeakPtr(); return std::move(result); } @@ -121,7 +123,7 @@ std::unique_ptr<FakeDesktopEnvironment> result( new FakeDesktopEnvironment(capture_thread_, options)); result->set_frame_generator(frame_generator_); - last_desktop_environment_ = result->AsWeakPtr(); + last_desktop_environment_ = result->weak_factory_.GetWeakPtr(); return std::move(result); }
diff --git a/remoting/host/fake_desktop_environment.h b/remoting/host/fake_desktop_environment.h index 116678e..28a0406 100644 --- a/remoting/host/fake_desktop_environment.h +++ b/remoting/host/fake_desktop_environment.h
@@ -21,8 +21,7 @@ namespace remoting { -class FakeInputInjector : public InputInjector, - public base::SupportsWeakPtr<FakeInputInjector> { +class FakeInputInjector : public InputInjector { public: FakeInputInjector(); ~FakeInputInjector() override; @@ -53,11 +52,17 @@ } private: + friend class FakeDesktopEnvironment; + std::vector<protocol::KeyEvent>* key_events_ = nullptr; std::vector<protocol::TextEvent>* text_events_ = nullptr; std::vector<protocol::MouseEvent>* mouse_events_ = nullptr; std::vector<protocol::TouchEvent>* touch_events_ = nullptr; std::vector<protocol::ClipboardEvent>* clipboard_events_ = nullptr; + + base::WeakPtrFactory<FakeInputInjector> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeInputInjector); }; class FakeScreenControls : public ScreenControls { @@ -69,9 +74,7 @@ void SetScreenResolution(const ScreenResolution& resolution) override; }; -class FakeDesktopEnvironment - : public DesktopEnvironment, - public base::SupportsWeakPtr<FakeDesktopEnvironment> { +class FakeDesktopEnvironment : public DesktopEnvironment { public: explicit FakeDesktopEnvironment( scoped_refptr<base::SingleThreadTaskRunner> capture_thread, @@ -103,6 +106,8 @@ } private: + friend class FakeDesktopEnvironmentFactory; + scoped_refptr<base::SingleThreadTaskRunner> capture_thread_; protocol::FakeDesktopCapturer::FrameGenerator frame_generator_; @@ -110,6 +115,8 @@ const DesktopEnvironmentOptions options_; + base::WeakPtrFactory<FakeDesktopEnvironment> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(FakeDesktopEnvironment); };
diff --git a/remoting/host/fake_host_status_monitor.h b/remoting/host/fake_host_status_monitor.h deleted file mode 100644 index 7c9e7ee..0000000 --- a/remoting/host/fake_host_status_monitor.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_FAKE_HOST_STATUS_MONITOR_H_ -#define REMOTING_HOST_FAKE_HOST_STATUS_MONITOR_H_ - -#include "base/memory/weak_ptr.h" -#include "remoting/host/host_status_monitor.h" - -namespace remoting { - -// An implementation of HostStatusMonitor that does nothing. -class FakeHostStatusMonitor - : public base::SupportsWeakPtr<FakeHostStatusMonitor>, - public HostStatusMonitor { - public: - ~FakeHostStatusMonitor() override {} - - // HostStatusMonitor interface. - void AddStatusObserver(HostStatusObserver* observer) override {} - void RemoveStatusObserver(HostStatusObserver* observer) override {} -}; - -} // namespace remoting - -#endif // REMOTING_HOST_FAKE_HOST_STATUS_MONITOR_H_
diff --git a/remoting/host/host_event_logger.h b/remoting/host/host_event_logger.h index e7ab5a9..254aa968 100644 --- a/remoting/host/host_event_logger.h +++ b/remoting/host/host_event_logger.h
@@ -23,7 +23,7 @@ // Creates an event-logger that monitors host status changes and logs // corresponding events to the OS-specific log (syslog/EventLog). static std::unique_ptr<HostEventLogger> Create( - base::WeakPtr<HostStatusMonitor> monitor, + scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name); protected:
diff --git a/remoting/host/host_event_logger_posix.cc b/remoting/host/host_event_logger_posix.cc index 7b7112ee..2ce48ad9 100644 --- a/remoting/host/host_event_logger_posix.cc +++ b/remoting/host/host_event_logger_posix.cc
@@ -26,7 +26,7 @@ class HostEventLoggerPosix : public HostEventLogger, public HostStatusObserver { public: - HostEventLoggerPosix(base::WeakPtr<HostStatusMonitor> monitor, + HostEventLoggerPosix(scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name); ~HostEventLoggerPosix() override; @@ -45,7 +45,7 @@ private: void Log(const std::string& message); - base::WeakPtr<HostStatusMonitor> monitor_; + scoped_refptr<HostStatusMonitor> monitor_; std::string application_name_; DISALLOW_COPY_AND_ASSIGN(HostEventLoggerPosix); @@ -54,17 +54,15 @@ } //namespace HostEventLoggerPosix::HostEventLoggerPosix( - base::WeakPtr<HostStatusMonitor> monitor, + scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name) - : monitor_(monitor), - application_name_(application_name) { + : monitor_(monitor), application_name_(application_name) { openlog(application_name_.c_str(), 0, LOG_USER); monitor_->AddStatusObserver(this); } HostEventLoggerPosix::~HostEventLoggerPosix() { - if (monitor_.get()) - monitor_->RemoveStatusObserver(this); + monitor_->RemoveStatusObserver(this); closelog(); } @@ -106,7 +104,7 @@ // static std::unique_ptr<HostEventLogger> HostEventLogger::Create( - base::WeakPtr<HostStatusMonitor> monitor, + scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name) { return base::WrapUnique(new HostEventLoggerPosix(monitor, application_name)); }
diff --git a/remoting/host/host_event_logger_win.cc b/remoting/host/host_event_logger_win.cc index 70135aa9a..77326758 100644 --- a/remoting/host/host_event_logger_win.cc +++ b/remoting/host/host_event_logger_win.cc
@@ -28,7 +28,7 @@ class HostEventLoggerWin : public HostEventLogger, public HostStatusObserver { public: - HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor, + HostEventLoggerWin(scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name); ~HostEventLoggerWin() override; @@ -49,20 +49,19 @@ void LogString(WORD type, DWORD event_id, const std::string& string); void Log(WORD type, DWORD event_id, const std::vector<std::string>& strings); - base::WeakPtr<HostStatusMonitor> monitor_; + scoped_refptr<HostStatusMonitor> monitor_; // The handle of the application event log. - HANDLE event_log_; + HANDLE event_log_ = nullptr; DISALLOW_COPY_AND_ASSIGN(HostEventLoggerWin); }; -} //namespace +} // namespace -HostEventLoggerWin::HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor, +HostEventLoggerWin::HostEventLoggerWin(scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name) - : monitor_(monitor), - event_log_(nullptr) { + : monitor_(monitor) { event_log_ = RegisterEventSourceW( nullptr, base::UTF8ToUTF16(application_name).c_str()); if (event_log_ != nullptr) { @@ -74,8 +73,7 @@ HostEventLoggerWin::~HostEventLoggerWin() { if (event_log_ != nullptr) { - if (monitor_) - monitor_->RemoveStatusObserver(this); + monitor_->RemoveStatusObserver(this); DeregisterEventSource(event_log_); } } @@ -128,14 +126,8 @@ raw_strings[i] = utf16_strings[i].c_str(); } - if (!ReportEventW(event_log_, - type, - HOST_CATEGORY, - event_id, - nullptr, - static_cast<WORD>(raw_strings.size()), - 0, - &raw_strings[0], + if (!ReportEventW(event_log_, type, HOST_CATEGORY, event_id, nullptr, + static_cast<WORD>(raw_strings.size()), 0, &raw_strings[0], nullptr)) { PLOG(ERROR) << "Failed to write an event to the event log"; } @@ -151,9 +143,9 @@ // static std::unique_ptr<HostEventLogger> HostEventLogger::Create( - base::WeakPtr<HostStatusMonitor> monitor, + scoped_refptr<HostStatusMonitor> monitor, const std::string& application_name) { - return base::WrapUnique(new HostEventLoggerWin(monitor, application_name)); + return base::MakeUnique<HostEventLoggerWin>(monitor, application_name); } } // namespace remoting
diff --git a/remoting/host/host_power_save_blocker.cc b/remoting/host/host_power_save_blocker.cc index c93f71c..a461115d 100644 --- a/remoting/host/host_power_save_blocker.cc +++ b/remoting/host/host_power_save_blocker.cc
@@ -13,7 +13,7 @@ namespace remoting { HostPowerSaveBlocker::HostPowerSaveBlocker( - base::WeakPtr<HostStatusMonitor> monitor, + scoped_refptr<HostStatusMonitor> monitor, const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) : monitor_(monitor), @@ -24,18 +24,14 @@ } HostPowerSaveBlocker::~HostPowerSaveBlocker() { - if (monitor_.get()) { - monitor_->RemoveStatusObserver(this); - } + monitor_->RemoveStatusObserver(this); } void HostPowerSaveBlocker::OnClientConnected(const std::string& jid) { blocker_.reset(new device::PowerSaveBlocker( device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - device::PowerSaveBlocker::kReasonOther, - "Remoting session is active", - ui_task_runner_, - file_task_runner_)); + device::PowerSaveBlocker::kReasonOther, "Remoting session is active", + ui_task_runner_, file_task_runner_)); } void HostPowerSaveBlocker::OnClientDisconnected(const std::string& jid) {
diff --git a/remoting/host/host_power_save_blocker.h b/remoting/host/host_power_save_blocker.h index 1f31363..4348293 100644 --- a/remoting/host/host_power_save_blocker.h +++ b/remoting/host/host_power_save_blocker.h
@@ -28,7 +28,7 @@ class HostPowerSaveBlocker : public HostStatusObserver { public: HostPowerSaveBlocker( - base::WeakPtr<HostStatusMonitor> monitor, + scoped_refptr<HostStatusMonitor> monitor, const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner); @@ -40,7 +40,8 @@ private: friend class HostPowerSaveBlockerTest; - base::WeakPtr<HostStatusMonitor> monitor_; + scoped_refptr<HostStatusMonitor> monitor_; + scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; std::unique_ptr<device::PowerSaveBlocker> blocker_;
diff --git a/remoting/host/host_power_save_blocker_unittest.cc b/remoting/host/host_power_save_blocker_unittest.cc index 77124fc..6b501861 100644 --- a/remoting/host/host_power_save_blocker_unittest.cc +++ b/remoting/host/host_power_save_blocker_unittest.cc
@@ -9,7 +9,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread.h" -#include "remoting/host/fake_host_status_monitor.h" +#include "remoting/host/host_status_monitor.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { @@ -25,18 +25,18 @@ base::MessageLoopForUI ui_message_loop_; base::Thread blocking_thread_; - FakeHostStatusMonitor monitor_; + scoped_refptr<HostStatusMonitor> monitor_; std::unique_ptr<HostPowerSaveBlocker> blocker_; }; HostPowerSaveBlockerTest::HostPowerSaveBlockerTest() - : blocking_thread_("block-thread") {} + : blocking_thread_("block-thread"), monitor_(new HostStatusMonitor()) {} void HostPowerSaveBlockerTest::SetUp() { ASSERT_TRUE(blocking_thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)) && blocking_thread_.WaitUntilThreadStarted()); - blocker_.reset(new HostPowerSaveBlocker(monitor_.AsWeakPtr(), + blocker_.reset(new HostPowerSaveBlocker(monitor_, ui_message_loop_.task_runner(), blocking_thread_.task_runner())); }
diff --git a/remoting/host/host_status_logger.cc b/remoting/host/host_status_logger.cc index b81e03297..07dd716 100644 --- a/remoting/host/host_status_logger.cc +++ b/remoting/host/host_status_logger.cc
@@ -13,7 +13,7 @@ namespace remoting { -HostStatusLogger::HostStatusLogger(base::WeakPtr<HostStatusMonitor> monitor, +HostStatusLogger::HostStatusLogger(scoped_refptr<HostStatusMonitor> monitor, ServerLogEntry::Mode mode, SignalStrategy* signal_strategy, const std::string& directory_bot_jid) @@ -24,8 +24,7 @@ HostStatusLogger::~HostStatusLogger() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (monitor_.get()) - monitor_->RemoveStatusObserver(this); + monitor_->RemoveStatusObserver(this); } void HostStatusLogger::LogSessionStateChange(const std::string& jid,
diff --git a/remoting/host/host_status_logger.h b/remoting/host/host_status_logger.h index 55771cc3..2a3f4582 100644 --- a/remoting/host/host_status_logger.h +++ b/remoting/host/host_status_logger.h
@@ -23,10 +23,10 @@ // They do not contain any personally identifiable information. class HostStatusLogger : public HostStatusObserver { public: - HostStatusLogger(base::WeakPtr<HostStatusMonitor> monitor, - ServerLogEntry::Mode mode, - SignalStrategy* signal_strategy, - const std::string& directory_bot_jid); + HostStatusLogger(scoped_refptr<HostStatusMonitor> monitor, + ServerLogEntry::Mode mode, + SignalStrategy* signal_strategy, + const std::string& directory_bot_jid); ~HostStatusLogger() override; // Logs a session state change. Currently, this is either @@ -46,7 +46,7 @@ private: LogToServer log_to_server_; - base::WeakPtr<HostStatusMonitor> monitor_; + scoped_refptr<HostStatusMonitor> monitor_; // A map from client JID to the route type of that client's connection to // this host.
diff --git a/remoting/host/host_status_logger_unittest.cc b/remoting/host/host_status_logger_unittest.cc index 01160ee..7d2a413 100644 --- a/remoting/host/host_status_logger_unittest.cc +++ b/remoting/host/host_status_logger_unittest.cc
@@ -6,7 +6,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "remoting/host/fake_host_status_monitor.h" +#include "remoting/host/host_status_monitor.h" #include "remoting/signaling/mock_signal_strategy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" @@ -124,14 +124,14 @@ class HostStatusLoggerTest : public testing::Test { public: - HostStatusLoggerTest() : signal_strategy_(SignalingAddress(kHostJid)) {} + HostStatusLoggerTest() + : signal_strategy_(SignalingAddress(kHostJid)), + host_status_monitor_(new HostStatusMonitor()) {} void SetUp() override { EXPECT_CALL(signal_strategy_, AddListener(_)); host_status_logger_.reset( - new HostStatusLogger(host_status_monitor_.AsWeakPtr(), - ServerLogEntry::ME2ME, - &signal_strategy_, - kTestBotJid)); + new HostStatusLogger(host_status_monitor_, ServerLogEntry::ME2ME, + &signal_strategy_, kTestBotJid)); EXPECT_CALL(signal_strategy_, RemoveListener(_)); } @@ -139,7 +139,7 @@ base::MessageLoop message_loop_; MockSignalStrategy signal_strategy_; std::unique_ptr<HostStatusLogger> host_status_logger_; - FakeHostStatusMonitor host_status_monitor_; + scoped_refptr<HostStatusMonitor> host_status_monitor_; }; TEST_F(HostStatusLoggerTest, SendNow) {
diff --git a/remoting/host/host_status_monitor.cc b/remoting/host/host_status_monitor.cc new file mode 100644 index 0000000..5a547ee --- /dev/null +++ b/remoting/host/host_status_monitor.cc
@@ -0,0 +1,20 @@ +// 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 "remoting/host/host_status_monitor.h" + +namespace remoting { + +HostStatusMonitor::HostStatusMonitor() {} +HostStatusMonitor::~HostStatusMonitor() {} + +void HostStatusMonitor::AddStatusObserver(HostStatusObserver* observer) { + observers_.AddObserver(observer); +} + +void HostStatusMonitor::RemoveStatusObserver(HostStatusObserver* observer) { + observers_.RemoveObserver(observer); +} + +} // namespace remoting
diff --git a/remoting/host/host_status_monitor.h b/remoting/host/host_status_monitor.h index 6cc80cb..96e6420 100644 --- a/remoting/host/host_status_monitor.h +++ b/remoting/host/host_status_monitor.h
@@ -5,18 +5,32 @@ #ifndef REMOTING_HOST_HOST_STATUS_MONITOR_H_ #define REMOTING_HOST_HOST_STATUS_MONITOR_H_ +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" + namespace remoting { class HostStatusObserver; -// Interface for registering host status observers. -class HostStatusMonitor { +// Helper used to deliver host status notifications to observers. +class HostStatusMonitor : public base::RefCountedThreadSafe<HostStatusMonitor> { public: - virtual ~HostStatusMonitor() {} + HostStatusMonitor(); // Add/Remove |observer| to/from the list of status observers. - virtual void AddStatusObserver(HostStatusObserver* observer) = 0; - virtual void RemoveStatusObserver(HostStatusObserver* observer) = 0; + void AddStatusObserver(HostStatusObserver* observer); + void RemoveStatusObserver(HostStatusObserver* observer); + + const base::ObserverList<HostStatusObserver>& observers() { + return observers_; + }; + + protected: + friend class base::RefCountedThreadSafe<HostStatusMonitor>; + + base::ObserverList<HostStatusObserver> observers_; + + virtual ~HostStatusMonitor(); }; } // namespace remoting
diff --git a/remoting/host/host_status_observer.h b/remoting/host/host_status_observer.h index 2b6282d..349a749 100644 --- a/remoting/host/host_status_observer.h +++ b/remoting/host/host_status_observer.h
@@ -11,15 +11,15 @@ namespace protocol { struct TransportRoute; -}; +} // namespace protocol // Interface for host status observer. All methods are invoked on the // network thread. Observers must not tear-down ChromotingHost state // on receipt of these callbacks; they are purely informational. class HostStatusObserver { public: - HostStatusObserver() { } - virtual ~HostStatusObserver() { } + HostStatusObserver() {} + virtual ~HostStatusObserver() {} // Called when an unauthorized user attempts to connect to the host. virtual void OnAccessDenied(const std::string& jid) {}
diff --git a/remoting/host/ipc_host_event_logger.cc b/remoting/host/ipc_host_event_logger.cc index 501e20ca..b3240f60 100644 --- a/remoting/host/ipc_host_event_logger.cc +++ b/remoting/host/ipc_host_event_logger.cc
@@ -13,18 +13,16 @@ namespace remoting { -IpcHostEventLogger::IpcHostEventLogger(base::WeakPtr<HostStatusMonitor> monitor, +IpcHostEventLogger::IpcHostEventLogger(scoped_refptr<HostStatusMonitor> monitor, IPC::Sender* daemon_channel) - : daemon_channel_(daemon_channel), - monitor_(monitor) { + : daemon_channel_(daemon_channel), monitor_(monitor) { monitor_->AddStatusObserver(this); } IpcHostEventLogger::~IpcHostEventLogger() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (monitor_.get()) - monitor_->RemoveStatusObserver(this); + monitor_->RemoveStatusObserver(this); } void IpcHostEventLogger::OnAccessDenied(const std::string& jid) {
diff --git a/remoting/host/ipc_host_event_logger.h b/remoting/host/ipc_host_event_logger.h index b292fa45..2157b8f 100644 --- a/remoting/host/ipc_host_event_logger.h +++ b/remoting/host/ipc_host_event_logger.h
@@ -10,7 +10,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/weak_ptr.h" +#include "base/memory/ref_counted.h" #include "base/sequence_checker.h" #include "remoting/host/host_event_logger.h" #include "remoting/host/host_status_observer.h" @@ -26,7 +26,7 @@ class IpcHostEventLogger : public HostEventLogger, public HostStatusObserver { public: // Initializes the logger. |daemon_channel| must outlive this object. - IpcHostEventLogger(base::WeakPtr<HostStatusMonitor> monitor, + IpcHostEventLogger(scoped_refptr<HostStatusMonitor> monitor, IPC::Sender* daemon_channel); ~IpcHostEventLogger() override; @@ -45,7 +45,7 @@ // Used to report host status events to the daemon. IPC::Sender* daemon_channel_; - base::WeakPtr<HostStatusMonitor> monitor_; + scoped_refptr<HostStatusMonitor> monitor_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index 9575eda..7f49098 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc
@@ -179,14 +179,14 @@ host_context_->audio_task_runner(), host_context_->video_encode_task_runner(), DesktopEnvironmentOptions::CreateDefault())); - host_->AddStatusObserver(this); + host_->status_monitor()->AddStatusObserver(this); host_status_logger_.reset( - new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::IT2ME, + new HostStatusLogger(host_->status_monitor(), ServerLogEntry::IT2ME, signal_strategy_.get(), directory_bot_jid)); // Create event logger. host_event_logger_ = - HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName); + HostEventLogger::Create(host_->status_monitor(), kApplicationName); // Connect signaling and start the host. signal_strategy_->Connect(); @@ -457,15 +457,15 @@ confirmation_dialog_proxy_.reset(); - host_event_logger_.reset(); if (host_) { - host_->RemoveStatusObserver(this); - host_.reset(); + host_->status_monitor()->RemoveStatusObserver(this); + host_ = nullptr; } - register_request_.reset(); - host_status_logger_.reset(); - signal_strategy_.reset(); + register_request_ = nullptr; + host_status_logger_ = nullptr; + signal_strategy_ = nullptr; + host_event_logger_ = nullptr; // Post tasks to delete UI objects on the UI thread. host_context_->ui_task_runner()->DeleteSoon(
diff --git a/remoting/host/linux/certificate_watcher.cc b/remoting/host/linux/certificate_watcher.cc index c47c462..7b3bd3f 100644 --- a/remoting/host/linux/certificate_watcher.cc +++ b/remoting/host/linux/certificate_watcher.cc
@@ -210,7 +210,7 @@ VLOG(1) << "Started watching certificate changes."; } -void CertificateWatcher::SetMonitor(base::WeakPtr<HostStatusMonitor> monitor) { +void CertificateWatcher::SetMonitor(scoped_refptr<HostStatusMonitor> monitor) { DCHECK(is_started()); if (monitor_) { monitor_->RemoveStatusObserver(this);
diff --git a/remoting/host/linux/certificate_watcher.h b/remoting/host/linux/certificate_watcher.h index 720e34d..c243e31 100644 --- a/remoting/host/linux/certificate_watcher.h +++ b/remoting/host/linux/certificate_watcher.h
@@ -48,7 +48,7 @@ // the inhibit mode. Should be called after the watcher starts. // Adds |this| as an observer to the monitor. // Removes |this| as an observer from the old monitor if it is not null. - void SetMonitor(base::WeakPtr<HostStatusMonitor> monitor); + void SetMonitor(scoped_refptr<HostStatusMonitor> monitor); // HostStatusObserver interface. void OnClientConnected(const std::string& jid) override; @@ -68,8 +68,8 @@ // |inhibit_restart_scheduled_| flag is set to true. void DatabaseChanged(); - // Reference to the monitor - base::WeakPtr<HostStatusMonitor> monitor_; + // Reference to the monitor. + scoped_refptr<HostStatusMonitor> monitor_; // Called when a restart is scheduled. base::Closure restart_action_;
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 5c10a908..944a92b 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -744,7 +744,7 @@ context_->file_task_runner())); cert_watcher_->Start(); } - cert_watcher_->SetMonitor(host_->AsWeakPtr()); + cert_watcher_->SetMonitor(host_->status_monitor()); #endif scoped_refptr<protocol::TokenValidatorFactory> token_validator_factory = @@ -1503,22 +1503,21 @@ host_change_notification_listener_.reset(new HostChangeNotificationListener( this, host_id_, signal_strategy_.get(), directory_bot_jid_)); - host_status_logger_.reset(new HostStatusLogger( - host_->AsWeakPtr(), ServerLogEntry::ME2ME, - signal_strategy_.get(), directory_bot_jid_)); + host_status_logger_.reset( + new HostStatusLogger(host_->status_monitor(), ServerLogEntry::ME2ME, + signal_strategy_.get(), directory_bot_jid_)); power_save_blocker_.reset(new HostPowerSaveBlocker( - host_->AsWeakPtr(), - context_->ui_task_runner(), + host_->status_monitor(), context_->ui_task_runner(), context_->file_task_runner())); // Set up reporting the host status notifications. #if defined(REMOTING_MULTI_PROCESS) host_event_logger_.reset( - new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get())); + new IpcHostEventLogger(host_->status_monitor(), daemon_channel_.get())); #else // !defined(REMOTING_MULTI_PROCESS) host_event_logger_ = - HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName); + HostEventLogger::Create(host_->status_monitor(), kApplicationName); #endif // !defined(REMOTING_MULTI_PROCESS) host_->Start(host_owner_email_);
diff --git a/remoting/host/signaling_connector.cc b/remoting/host/signaling_connector.cc index b338072..9a99435 100644 --- a/remoting/host/signaling_connector.cc +++ b/remoting/host/signaling_connector.cc
@@ -50,7 +50,8 @@ auth_failed_callback_(auth_failed_callback), dns_blackhole_checker_(std::move(dns_blackhole_checker)), oauth_token_getter_(oauth_token_getter), - reconnect_attempts_(0) { + reconnect_attempts_(0), + weak_factory_(this) { DCHECK(!auth_failed_callback_.is_null()); DCHECK(dns_blackhole_checker_.get()); net::NetworkChangeNotifier::AddConnectionTypeObserver(this); @@ -184,8 +185,8 @@ if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { HOST_LOG << "Attempting to connect signaling."; - oauth_token_getter_->CallWithToken( - base::Bind(&SignalingConnector::OnAccessToken, AsWeakPtr())); + oauth_token_getter_->CallWithToken(base::Bind( + &SignalingConnector::OnAccessToken, weak_factory_.GetWeakPtr())); } }
diff --git a/remoting/host/signaling_connector.h b/remoting/host/signaling_connector.h index b057438..da6e17d1 100644 --- a/remoting/host/signaling_connector.h +++ b/remoting/host/signaling_connector.h
@@ -24,8 +24,7 @@ // backoff. It also monitors network state and reconnects signalling // whenever connection type changes or IP address changes. class SignalingConnector - : public base::SupportsWeakPtr<SignalingConnector>, - public SignalStrategy::Listener, + : public SignalStrategy::Listener, public net::NetworkChangeNotifier::ConnectionTypeObserver, public net::NetworkChangeNotifier::IPAddressObserver { public: @@ -72,6 +71,8 @@ SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<SignalingConnector> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(SignalingConnector); };
diff --git a/remoting/ios/app/BUILD.gn b/remoting/ios/app/BUILD.gn index d941e5a..542aed00 100644 --- a/remoting/ios/app/BUILD.gn +++ b/remoting/ios/app/BUILD.gn
@@ -46,6 +46,8 @@ "remoting_theme.mm", "remoting_view_controller.h", "remoting_view_controller.mm", + "session_reconnect_view.h", + "session_reconnect_view.mm", ] deps = [
diff --git a/remoting/ios/app/client_connection_view_controller.h b/remoting/ios/app/client_connection_view_controller.h index efc5b56..866d495 100644 --- a/remoting/ios/app/client_connection_view_controller.h +++ b/remoting/ios/app/client_connection_view_controller.h
@@ -14,7 +14,9 @@ ClientViewConnecting, ClientViewPinPrompt, ClientViewConnected, + ClientViewReconnect, ClientViewClosed, + ClientViewError, }; // This is the view that shows the user feedback while the client connection is
diff --git a/remoting/ios/app/client_connection_view_controller.mm b/remoting/ios/app/client_connection_view_controller.mm index 888ee2c..272fc2f 100644 --- a/remoting/ios/app/client_connection_view_controller.mm +++ b/remoting/ios/app/client_connection_view_controller.mm
@@ -12,9 +12,11 @@ #import "ios/third_party/material_components_ios/src/components/ActivityIndicator/src/MDCActivityIndicator.h" #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" #import "ios/third_party/material_components_ios/src/components/NavigationBar/src/MaterialNavigationBar.h" +#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h" #import "remoting/ios/app/host_view_controller.h" #import "remoting/ios/app/pin_entry_view.h" #import "remoting/ios/app/remoting_theme.h" +#import "remoting/ios/app/session_reconnect_view.h" #import "remoting/ios/domain/client_session_details.h" #import "remoting/ios/domain/host_info.h" #import "remoting/ios/facade/remoting_authentication.h" @@ -31,7 +33,10 @@ static const CGFloat kPinEntryViewWidth = 240.f; static const CGFloat kPinEntryViewHeight = 90.f; -static const CGFloat kCenterShift = -80.f; +static const CGFloat kReconnectViewWidth = 120.f; +static const CGFloat kReconnectViewHeight = 90.f; + +static const CGFloat kTopPadding = 240.f; static const CGFloat kPadding = 20.f; static const CGFloat kMargin = 20.f; @@ -39,14 +44,20 @@ static const CGFloat kKeyboardAnimationTime = 0.3; -@interface ClientConnectionViewController ()<PinEntryDelegate> { +@interface ClientConnectionViewController ()<PinEntryDelegate, + SessionReconnectViewDelegate> { UIImageView* _iconView; MDCActivityIndicator* _activityIndicator; + NSLayoutConstraint* _activityIndicatorTopConstraintFull; + NSLayoutConstraint* _activityIndicatorTopConstraintKeyboard; UILabel* _statusLabel; MDCNavigationBar* _navBar; PinEntryView* _pinEntryView; + SessionReconnectView* _reconnectView; NSString* _remoteHostName; RemotingClient* _client; + SessionErrorCode _lastError; + HostInfo* _hostInfo; } @end @@ -57,17 +68,7 @@ - (instancetype)initWithHostInfo:(HostInfo*)hostInfo { self = [super init]; if (self) { - _client = [[RemotingClient alloc] init]; - - __weak RemotingClient* weakClient = _client; - [RemotingService.instance.authentication - callbackWithAccessToken:^(RemotingAuthenticationStatus status, - NSString* userEmail, NSString* accessToken) { - [weakClient connectToHost:hostInfo - username:userEmail - accessToken:accessToken]; - }]; - + _hostInfo = hostInfo; _remoteHostName = hostInfo.hostName; // TODO(yuweih): This logic may be reused by other views. @@ -102,78 +103,67 @@ constraintEqualToAnchor:[self.view trailingAnchor]], [[_navBar heightAnchor] constraintEqualToConstant:kBarHeight], ]]; + + [self attemptConnectionToHost]; } return self; } -#pragma mark - UIViewController - -- (void)loadView { - [super loadView]; - - self.view.backgroundColor = RemotingTheme.connectionViewBackgroundColor; - - _activityIndicator = [[MDCActivityIndicator alloc] initWithFrame:CGRectZero]; - [self.view addSubview:_activityIndicator]; - - _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - [self.view addSubview:_statusLabel]; - - _iconView = [[UIImageView alloc] initWithFrame:CGRectZero]; - [self.view addSubview:_iconView]; - - _pinEntryView = [[PinEntryView alloc] init]; - [self.view addSubview:_pinEntryView]; - _pinEntryView.delegate = self; +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; } +#pragma mark - UIViewController + - (void)viewDidLoad { [super viewDidLoad]; + self.view.backgroundColor = RemotingTheme.connectionViewBackgroundColor; + _activityIndicator = [[MDCActivityIndicator alloc] initWithFrame:CGRectZero]; + _activityIndicator.radius = kActivityIndicatorRadius; + _activityIndicator.trackEnabled = YES; + _activityIndicator.strokeWidth = kActivityIndicatorStrokeWidth; + _activityIndicator.cycleColors = @[ UIColor.whiteColor ]; + _activityIndicator.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_activityIndicator]; + + _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _statusLabel.numberOfLines = 1; + _statusLabel.lineBreakMode = NSLineBreakByTruncatingTail; + _statusLabel.textColor = [UIColor whiteColor]; + _statusLabel.textAlignment = NSTextAlignmentCenter; + _statusLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_statusLabel]; + + _iconView = [[UIImageView alloc] initWithFrame:CGRectZero]; _iconView.contentMode = UIViewContentModeCenter; _iconView.alpha = 0.87f; _iconView.backgroundColor = RemotingTheme.onlineHostColor; _iconView.layer.cornerRadius = kIconRadius; _iconView.layer.masksToBounds = YES; _iconView.image = RemotingTheme.desktopIcon; + _iconView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_iconView]; - _activityIndicator.radius = kActivityIndicatorRadius; - _activityIndicator.trackEnabled = YES; - _activityIndicator.strokeWidth = kActivityIndicatorStrokeWidth; - _activityIndicator.cycleColors = @[ UIColor.whiteColor ]; + _reconnectView = [[SessionReconnectView alloc] initWithFrame:CGRectZero]; + _reconnectView.hidden = YES; + _reconnectView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_reconnectView]; + _reconnectView.delegate = self; - _statusLabel.numberOfLines = 1; - _statusLabel.lineBreakMode = NSLineBreakByTruncatingTail; - _statusLabel.textColor = [UIColor whiteColor]; - _statusLabel.textAlignment = NSTextAlignmentCenter; - + _pinEntryView = [[PinEntryView alloc] init]; _pinEntryView.hidden = YES; -} + _pinEntryView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_pinEntryView]; + _pinEntryView.delegate = self; -- (void)viewWillLayoutSubviews { - [super viewWillLayoutSubviews]; + _reconnectView.hidden = YES; - _iconView.frame = CGRectMake(0, 0, kIconRadius * 2, kIconRadius * 2.f); - _iconView.center = - CGPointMake(self.view.center.x, self.view.center.y + kCenterShift); - - [_activityIndicator sizeToFit]; - _activityIndicator.center = _iconView.center; - - _statusLabel.frame = - CGRectMake(kMargin, _activityIndicator.center.y + kIconRadius + kPadding, - self.view.frame.size.width - kMargin * 2.f, - _statusLabel.font.pointSize * _statusLabel.numberOfLines); - - _pinEntryView.frame = CGRectMake( - (self.view.frame.size.width - kPinEntryViewWidth) / 2.f, - _statusLabel.frame.origin.y + _statusLabel.frame.size.height + kPadding, - kPinEntryViewWidth, kPinEntryViewHeight); -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [self.navigationController setNavigationBarHidden:YES animated:animated]; + [self + initializeLayoutConstraintsWithViews:NSDictionaryOfVariableBindings( + _activityIndicator, _statusLabel, + _iconView, _reconnectView, + _pinEntryView)]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -182,6 +172,108 @@ object:nil]; } +- (void)initializeLayoutConstraintsWithViews:(NSDictionary*)views { + // Metrics to use in visual format strings. + NSDictionary* layoutMetrics = @{ + @"padding" : @(kPadding), + @"margin" : @(kMargin), + @"topPadding" : @(kTopPadding), + @"iconDiameter" : @(kIconRadius * 2), + @"pinEntryViewWidth" : @(kPinEntryViewWidth), + @"pinEntryViewHeight" : @(kPinEntryViewHeight), + @"reconnectViewWidth" : @(kReconnectViewWidth), + @"reconnectViewHeight" : @(kReconnectViewHeight), + }; + [_activityIndicator sizeToFit]; + NSString* f; + + // Horizontal constraints: + [self.view addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat:@"H:[_iconView(iconDiameter)]" + options:0 + metrics:layoutMetrics + views:views]]; + + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat: + @"H:|-margin-[_statusLabel]-margin-|" + options:0 + metrics:layoutMetrics + views:views]]; + + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat: + @"H:[_pinEntryView(pinEntryViewWidth)]" + options:0 + metrics:layoutMetrics + views:views]]; + + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat: + @"H:[_reconnectView(reconnectViewWidth)]" + options:0 + metrics:layoutMetrics + views:views]]; + + // Anchors: + _activityIndicatorTopConstraintFull = + [_activityIndicator.topAnchor constraintEqualToAnchor:self.view.topAnchor + constant:kTopPadding]; + _activityIndicatorTopConstraintFull.active = YES; + + [_iconView.centerYAnchor + constraintEqualToAnchor:_activityIndicator.centerYAnchor] + .active = YES; + + // Vertical constraints: + [self.view addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat:@"V:[_iconView(iconDiameter)]" + options:0 + metrics:layoutMetrics + views:views]]; + + [self.view addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat: + @"V:[_activityIndicator]-(padding)-[_statusLabel]" + options:NSLayoutFormatAlignAllCenterX + metrics:layoutMetrics + views:views]]; + + [self.view addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat: + @"V:[_iconView]-(padding)-[_statusLabel]" + options:NSLayoutFormatAlignAllCenterX + metrics:layoutMetrics + views:views]]; + + f = @"V:[_statusLabel]-(padding)-[_pinEntryView(pinEntryViewHeight)]"; + [self.view addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat:f + options:NSLayoutFormatAlignAllCenterX + metrics:layoutMetrics + views:views]]; + + f = @"V:[_statusLabel]-padding-[_reconnectView(reconnectViewHeight)]"; + [self.view addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat:f + options:NSLayoutFormatAlignAllCenterX + metrics:layoutMetrics + views:views]]; + + [self.view setNeedsUpdateConstraints]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:YES animated:animated]; +} + - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[NSNotificationCenter defaultCenter] @@ -202,7 +294,6 @@ - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [_activityIndicator stopAnimating]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (BOOL)prefersStatusBarHidden { @@ -211,35 +302,39 @@ #pragma mark - Keyboard +// TODO(nicholss): We need to listen to screen rotation and re-adjust the +// topAnchor. + - (void)keyboardWillShow:(NSNotification*)notification { CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] .size; - [UIView - animateWithDuration:kKeyboardAnimationTime - animations:^{ - CGRect f = self.view.frame; - CGFloat newHeight = - self.view.frame.size.height - keyboardSize.height; - CGFloat overlap = - newHeight - (_pinEntryView.frame.origin.y + - _pinEntryView.frame.size.height + kPadding); - if (overlap < 0) { - f.origin.y = overlap; - // TODO(yuweih): This may push the navigation bar off screen. - self.view.frame = f; - } - }]; + CGFloat newHeight = self.view.frame.size.height - keyboardSize.height; + CGFloat overlap = newHeight - (_pinEntryView.frame.origin.y + + _pinEntryView.frame.size.height + kPadding); + if (overlap > 0) { + overlap = 0; + } + _activityIndicatorTopConstraintKeyboard.active = NO; + _activityIndicatorTopConstraintKeyboard = [_activityIndicator.topAnchor + constraintEqualToAnchor:self.view.topAnchor + constant:kTopPadding + overlap]; + _activityIndicatorTopConstraintFull.active = NO; + _activityIndicatorTopConstraintKeyboard.active = YES; + [UIView animateWithDuration:kKeyboardAnimationTime + animations:^{ + [self.view layoutIfNeeded]; + }]; } - (void)keyboardWillHide:(NSNotification*)notification { + _activityIndicatorTopConstraintKeyboard.active = NO; + _activityIndicatorTopConstraintFull.active = YES; [UIView animateWithDuration:kKeyboardAnimationTime animations:^{ - CGRect f = self.view.frame; - f.origin.y = 0.f; - self.view.frame = f; + [self.view layoutIfNeeded]; }]; } @@ -257,23 +352,53 @@ case ClientViewConnected: [self showConnectedState]; break; + case ClientViewReconnect: + [self showReconnect]; + break; case ClientViewClosed: - [self dismissViewControllerAnimated:YES completion:nil]; + [self.navigationController popToRootViewControllerAnimated:YES]; + break; + case ClientViewError: + [self showError]; break; } } +#pragma mark - SessionReconnectViewDelegate + +- (void)didTapReconnect { + [self attemptConnectionToHost]; +} + #pragma mark - Private +- (void)attemptConnectionToHost { + _client = [[RemotingClient alloc] init]; + __weak RemotingClient* weakClient = _client; + __weak HostInfo* weakHostInfo = _hostInfo; + [RemotingService.instance.authentication + callbackWithAccessToken:^(RemotingAuthenticationStatus status, + NSString* userEmail, NSString* accessToken) { + [weakClient connectToHost:weakHostInfo + username:userEmail + accessToken:accessToken]; + }]; + [self setState:ClientViewConnecting]; +} + - (void)showConnectingState { [_pinEntryView endEditing:YES]; _statusLabel.text = [NSString stringWithFormat:@"Connecting to %@", _remoteHostName]; + + _pinEntryView.hidden = YES; + + _reconnectView.hidden = YES; + [_activityIndicator stopAnimating]; _activityIndicator.cycleColors = @[ [UIColor whiteColor] ]; _activityIndicator.indicatorMode = MDCActivityIndicatorModeIndeterminate; _activityIndicator.hidden = NO; - _pinEntryView.hidden = YES; [_activityIndicator startAnimating]; } @@ -281,7 +406,11 @@ _statusLabel.text = [NSString stringWithFormat:@"%@", _remoteHostName]; [_activityIndicator stopAnimating]; _activityIndicator.hidden = YES; + _pinEntryView.hidden = NO; + _reconnectView.hidden = YES; + + _reconnectView.hidden = YES; // TODO(yuweih): This may be called before viewDidAppear and miss the keyboard // callback. @@ -292,24 +421,113 @@ [_pinEntryView endEditing:YES]; _statusLabel.text = [NSString stringWithFormat:@"Connected to %@", _remoteHostName]; - _activityIndicator.progress = 0.0; + _pinEntryView.hidden = YES; + [_pinEntryView clearPinEntry]; + + _activityIndicator.progress = 0.0; _activityIndicator.hidden = NO; _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate; _activityIndicator.cycleColors = @[ [UIColor greenColor] ]; [_activityIndicator startAnimating]; _activityIndicator.progress = 1.0; + _reconnectView.hidden = YES; + + _reconnectView.hidden = YES; HostViewController* hostViewController = [[HostViewController alloc] initWithClient:_client]; _client = nil; - // Replaces current (topmost) view controller with |hostViewController|. - NSMutableArray* controllers = - [self.navigationController.viewControllers mutableCopy]; - [controllers removeLastObject]; - [controllers addObject:hostViewController]; - [self.navigationController setViewControllers:controllers animated:NO]; + [self.navigationController pushViewController:hostViewController animated:NO]; +} + +- (void)showReconnect { + _statusLabel.text = + [NSString stringWithFormat:@"Connection closed for %@", _remoteHostName]; + [_activityIndicator stopAnimating]; + _activityIndicator.hidden = YES; + + _pinEntryView.hidden = YES; + + _reconnectView.hidden = NO; + + [self.navigationController popToViewController:self animated:YES]; + [MDCSnackbarManager + showMessage:[MDCSnackbarMessage messageWithText:@"Connection Closed."]]; +} + +- (void)showError { + _statusLabel.text = + [NSString stringWithFormat:@"Error connecting to %@", _remoteHostName]; + + _pinEntryView.hidden = YES; + + _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate; + _activityIndicator.cycleColors = @[ [UIColor redColor] ]; + _activityIndicator.progress = 1.0; + _activityIndicator.hidden = NO; + [_activityIndicator startAnimating]; + + _reconnectView.hidden = NO; + + MDCSnackbarMessage* message = nil; + switch (_lastError) { + case SessionErrorOk: + // Do nothing. + break; + case SessionErrorPeerIsOffline: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorPeerIsOffline."]; + break; + case SessionErrorSessionRejected: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorSessionRejected."]; + break; + case SessionErrorIncompatibleProtocol: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorIncompatibleProtocol."]; + break; + case SessionErrorAuthenticationFailed: + message = [MDCSnackbarMessage messageWithText:@"Error: Invalid Pin."]; + [_pinEntryView clearPinEntry]; + break; + case SessionErrorInvalidAccount: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorInvalidAccount."]; + break; + case SessionErrorChannelConnectionError: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorChannelConnectionError."]; + break; + case SessionErrorSignalingError: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorSignalingError."]; + break; + case SessionErrorSignalingTimeout: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorSignalingTimeout."]; + break; + case SessionErrorHostOverload: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorHostOverload."]; + break; + case SessionErrorMaxSessionLength: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorMaxSessionLength."]; + break; + case SessionErrorHostConfigurationError: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorHostConfigurationError."]; + break; + case SessionErrorUnknownError: + message = [MDCSnackbarMessage + messageWithText:@"Error: SessionErrorUnknownError."]; + break; + } + if (message.text) { + [MDCSnackbarManager showMessage:message]; + } } - (void)didProvidePin:(NSString*)pin createPairing:(BOOL)createPairing { @@ -347,14 +565,17 @@ state = ClientViewConnected; break; case SessionFailed: - // TODO(nicholss): Implement an error screen. + state = ClientViewError; + break; case SessionClosed: - state = ClientViewClosed; + // If the session closes, offer the user to reconnect. + state = ClientViewReconnect; break; default: LOG(ERROR) << "Unknown State for Session, " << sessionDetails.state; return; } + _lastError = sessionDetails.error; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self setState:state]; }];
diff --git a/remoting/ios/app/host_view_controller.mm b/remoting/ios/app/host_view_controller.mm index 6bf3993..ea36e730 100644 --- a/remoting/ios/app/host_view_controller.mm +++ b/remoting/ios/app/host_view_controller.mm
@@ -310,7 +310,7 @@ void (^disconnectHandler)(UIAlertAction*) = ^(UIAlertAction*) { [_client disconnectFromHost]; - [self.navigationController popViewControllerAnimated:YES]; + [self.navigationController popToRootViewControllerAnimated:YES]; [_actionImageView setActive:NO animated:YES]; }; [alert addAction:[UIAlertAction actionWithTitle:@"Disconnect"
diff --git a/remoting/ios/app/pin_entry_view.h b/remoting/ios/app/pin_entry_view.h index acbf923..926831f 100644 --- a/remoting/ios/app/pin_entry_view.h +++ b/remoting/ios/app/pin_entry_view.h
@@ -20,6 +20,9 @@ // passcode. @interface PinEntryView : UIView +// Clears the pin entry view. +- (void)clearPinEntry; + // This delegate will handle interactions on the cells in the collection. @property(weak, nonatomic) id<PinEntryDelegate> delegate;
diff --git a/remoting/ios/app/pin_entry_view.mm b/remoting/ios/app/pin_entry_view.mm index 87a5a6b..9037e0f 100644 --- a/remoting/ios/app/pin_entry_view.mm +++ b/remoting/ios/app/pin_entry_view.mm
@@ -12,10 +12,12 @@ #import "remoting/ios/app/remoting_theme.h" static const CGFloat kMargin = 5.f; -static const CGFloat kPadding = 6.f; +static const CGFloat kPadding = 8.f; static const CGFloat kLineSpace = 12.f; -@interface PinEntryView () { +static const int kMinPinLength = 6; + +@interface PinEntryView ()<UITextFieldDelegate> { UISwitch* _pairingSwitch; UILabel* _pairingLabel; MDCFloatingButton* _pinButton; @@ -36,6 +38,7 @@ _pairingSwitch.tintColor = [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5]; _pairingSwitch.transform = CGAffineTransformMakeScale(0.5, 0.5); + _pairingSwitch.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_pairingSwitch]; _pairingLabel = [[UILabel alloc] init]; @@ -43,15 +46,21 @@ [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5]; _pairingLabel.font = [UIFont systemFontOfSize:12.f]; _pairingLabel.text = @"Remember my PIN on this device."; + _pairingLabel.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_pairingLabel]; _pinButton = [MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini]; - [_pinButton setImage:RemotingTheme.arrowIcon forState:UIControlStateNormal]; + [_pinButton + setImage:[RemotingTheme + .arrowIcon imageFlippedForRightToLeftLayoutDirection] + forState:UIControlStateNormal]; [_pinButton addTarget:self action:@selector(didTapPinEntry:) forControlEvents:UIControlEventTouchUpInside]; _pinButton.translatesAutoresizingMaskIntoConstraints = NO; + _pinButton.enabled = NO; + _pinButton.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_pinButton]; _pinEntry = [[UITextField alloc] init]; @@ -65,11 +74,51 @@ NSForegroundColorAttributeName : [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5] }]; + _pinEntry.translatesAutoresizingMaskIntoConstraints = NO; + _pinEntry.delegate = self; [self addSubview:_pinEntry]; + + [self + initializeLayoutConstraintsWithViews:NSDictionaryOfVariableBindings( + _pairingSwitch, _pairingLabel, + _pinButton, _pinEntry)]; } return self; } +- (void)initializeLayoutConstraintsWithViews:(NSDictionary*)views { + // Metrics to use in visual format strings. + NSDictionary* layoutMetrics = @{ + @"margin" : @(kMargin), + @"padding" : @(kPadding), + @"lineSpace" : @(kLineSpace), + }; + + [self addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat: + @"H:|-[_pinEntry]-(padding)-[_pinButton]-|" + options:NSLayoutFormatAlignAllCenterY + metrics:layoutMetrics + views:views]]; + + [self addConstraints: + [NSLayoutConstraint + constraintsWithVisualFormat: + @"H:|-[_pairingSwitch]-(padding)-[_pairingLabel]-|" + options:NSLayoutFormatAlignAllCenterY + metrics:layoutMetrics + views:views]]; + + [self addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat: + @"V:|-[_pinButton]-(lineSpace)-[_pairingSwitch]" + options:0 + metrics:layoutMetrics + views:views]]; + [self setNeedsUpdateConstraints]; +} + #pragma mark - UIView - (BOOL)canBecomeFirstResponder { @@ -84,31 +133,32 @@ return [_pinEntry endEditing:force]; } -- (void)layoutSubviews { - [super layoutSubviews]; +#pragma mark - UITextFieldDelegate - [_pinButton sizeToFit]; - CGFloat buttonSize = _pinButton.frame.size.width; // Assume circle. +- (BOOL)textField:(UITextField*)textField + shouldChangeCharactersInRange:(NSRange)range + replacementString:(NSString*)string { + if (textField == _pinEntry) { + NSUInteger length = _pinEntry.text.length - range.length + string.length; + _pinButton.enabled = length >= kMinPinLength; + } + return YES; +} - _pinEntry.frame = - CGRectMake(kMargin, 0.f, - self.frame.size.width - kPadding - kMargin * 2.f - buttonSize, - buttonSize); +- (BOOL)textFieldShouldReturn:(UITextField*)textField { + NSLog(@"textFieldShouldReturn"); + if ([_pinButton isEnabled]) { + [self didTapPinEntry:textField]; + return YES; + } + return NO; +} - [_pinButton sizeToFit]; - _pinButton.frame = - CGRectMake(self.frame.size.width - kPadding - kMargin - buttonSize, 0.f, - buttonSize, buttonSize); +#pragma mark - Public - [_pairingSwitch sizeToFit]; - _pairingSwitch.center = CGPointMake( - kMargin + _pairingSwitch.frame.size.width / 2.f, - buttonSize + _pairingSwitch.frame.size.height / 2.f + kLineSpace); - - _pairingLabel.frame = - CGRectMake(kMargin + _pairingSwitch.frame.size.width + kPadding, - buttonSize + kLineSpace, 0.f, 0.f); - [_pairingLabel sizeToFit]; +- (void)clearPinEntry { + _pinEntry.text = @""; + _pinButton.enabled = NO; } #pragma mark - Private
diff --git a/remoting/ios/app/remoting_view_controller.mm b/remoting/ios/app/remoting_view_controller.mm index 637febc..ea9666ea 100644 --- a/remoting/ios/app/remoting_view_controller.mm +++ b/remoting/ios/app/remoting_view_controller.mm
@@ -36,7 +36,8 @@ @interface RemotingViewController ()<HostCollectionViewControllerDelegate, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate> { - bool _isAuthenticated; + BOOL _isAuthenticated; + BOOL _showSignedInAccount; MDCDialogTransitionController* _dialogTransitionController; MDCAppBar* _appBar; HostCollectionViewController* _collectionViewController; @@ -54,6 +55,7 @@ - (instancetype)init { _isAuthenticated = NO; + _showSignedInAccount = YES; UICollectionViewFlowLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; layout.minimumInteritemSpacing = 0; @@ -147,19 +149,9 @@ object:nil]; } -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; - if (_isAuthenticated) { - [_remotingService requestHostListFetch]; - } - [self presentStatus]; -} - - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - if (!_isAuthenticated) { + if (!_remotingService.authentication.user.isAuthenticated) { [AppDelegate.instance presentSignInFlow]; MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; message.text = @"Please login."; @@ -178,22 +170,24 @@ } - (void)userDidUpdateNotification:(NSNotification*)notification { - [self nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self + nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; + }]; } #pragma mark - RemotingAuthenticationDelegate - (void)nowAuthenticated:(BOOL)authenticated { + _isAuthenticated = authenticated; if (authenticated) { - MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; - message.text = @"Logged In!"; - [MDCSnackbarManager showMessage:message]; + _showSignedInAccount = YES; + [self presentStatus]; } else { MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; - message.text = @"Not logged in."; + message.text = @"Please sign-in."; [MDCSnackbarManager showMessage:message]; } - _isAuthenticated = authenticated; [self refreshContent]; } @@ -268,7 +262,8 @@ - (void)presentStatus { MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; - if (_isAuthenticated) { + if (_isAuthenticated && _showSignedInAccount) { + _showSignedInAccount = NO; message.text = [NSString stringWithFormat:@"Currently signed in as %@.", _remotingService.authentication.user.userEmail];
diff --git a/remoting/ios/app/session_reconnect_view.h b/remoting/ios/app/session_reconnect_view.h new file mode 100644 index 0000000..2909cd53 --- /dev/null +++ b/remoting/ios/app/session_reconnect_view.h
@@ -0,0 +1,27 @@ +// 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 REMOTING_IOS_SESSON_RECONNECT_VIEW_H_ +#define REMOTING_IOS_SESSON_RECONNECT_VIEW_H_ + +#import <UIKit/UIKit.h> + +@protocol SessionReconnectViewDelegate<NSObject> + +// Notifies the delegate that the user tapped the reconnect button. +@optional +- (void)didTapReconnect; + +@end + +// This view is the container for a session connection error. It will display a +// reconnect button. +@interface SessionReconnectView : UIView + +// This delegate will handle interactions on the view. +@property(weak, nonatomic) id<SessionReconnectViewDelegate> delegate; + +@end + +#endif // REMOTING_IOS_SESSON_RECONNECT_VIEW_H_
diff --git a/remoting/ios/app/session_reconnect_view.mm b/remoting/ios/app/session_reconnect_view.mm new file mode 100644 index 0000000..3c3aafe --- /dev/null +++ b/remoting/ios/app/session_reconnect_view.mm
@@ -0,0 +1,75 @@ +// 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. + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "remoting/ios/app/session_reconnect_view.h" + +#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" +#import "remoting/ios/app/remoting_theme.h" + +static const CGFloat kReconnectButtonWidth = 120.f; +static const CGFloat kReconnectButtonHeight = 30.f; + +@interface SessionReconnectView () { + MDCRaisedButton* _reconnectButton; +} +@end + +@implementation SessionReconnectView + +@synthesize delegate = _delegate; + +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + + _reconnectButton = [[MDCRaisedButton alloc] init]; + [_reconnectButton setElevation:4.0f forState:UIControlStateNormal]; + [_reconnectButton setTitle:@"Reconnect" forState:UIControlStateNormal]; + [_reconnectButton addTarget:self + action:@selector(didTapReconnect:) + forControlEvents:UIControlEventTouchUpInside]; + _reconnectButton.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_reconnectButton]; + + [self initializeLayoutConstraintsWithViews:NSDictionaryOfVariableBindings( + _reconnectButton)]; + } + return self; +} + +- (void)initializeLayoutConstraintsWithViews:(NSDictionary*)views { + NSMutableArray* layoutConstraints = [NSMutableArray array]; + + [layoutConstraints addObject:[_reconnectButton.centerYAnchor + constraintEqualToAnchor:self.centerYAnchor]]; + + [layoutConstraints addObject:[_reconnectButton.centerXAnchor + constraintEqualToAnchor:self.centerXAnchor]]; + + [layoutConstraints + addObject:[_reconnectButton.widthAnchor + constraintEqualToConstant:kReconnectButtonWidth]]; + + [layoutConstraints + addObject:[_reconnectButton.heightAnchor + constraintEqualToConstant:kReconnectButtonHeight]]; + + [NSLayoutConstraint activateConstraints:layoutConstraints]; + [self setNeedsUpdateConstraints]; +} + +#pragma mark - Private + +- (void)didTapReconnect:(id)sender { + if ([_delegate respondsToSelector:@selector(didTapReconnect)]) { + [_delegate didTapReconnect]; + } +} + +@end
diff --git a/remoting/ios/domain/client_session_details.h b/remoting/ios/domain/client_session_details.h index 7309892..ee839b8 100644 --- a/remoting/ios/domain/client_session_details.h +++ b/remoting/ios/domain/client_session_details.h
@@ -22,6 +22,23 @@ SessionClosed, }; +// Session states that map to |remoting::protocol::ConnectionToHost::Error|. +typedef NS_ENUM(NSInteger, SessionErrorCode) { + SessionErrorOk = 0, + SessionErrorPeerIsOffline, + SessionErrorSessionRejected, + SessionErrorIncompatibleProtocol, + SessionErrorAuthenticationFailed, + SessionErrorInvalidAccount, + SessionErrorChannelConnectionError, + SessionErrorSignalingError, + SessionErrorSignalingTimeout, + SessionErrorHostOverload, + SessionErrorMaxSessionLength, + SessionErrorHostConfigurationError, + SessionErrorUnknownError, +}; + // The current state of a session and data needed for session context. @interface ClientSessionDetails : NSObject @@ -29,6 +46,8 @@ @property(nonatomic) HostInfo* hostInfo; // The current state of the session. @property(nonatomic, assign) SessionState state; +// The error assoiciated to the current state. +@property(nonatomic, assign) SessionErrorCode error; @end
diff --git a/remoting/ios/domain/client_session_details.mm b/remoting/ios/domain/client_session_details.mm index 7e73b95..8156c34 100644 --- a/remoting/ios/domain/client_session_details.mm +++ b/remoting/ios/domain/client_session_details.mm
@@ -14,6 +14,7 @@ @synthesize hostInfo = _hostInfo; @synthesize state = _state; +@synthesize error = _error; - (NSString*)description { return
diff --git a/remoting/ios/session/remoting_client.mm b/remoting/ios/session/remoting_client.mm index 3dfccc8..3154bdc 100644 --- a/remoting/ios/session/remoting_client.mm +++ b/remoting/ios/session/remoting_client.mm
@@ -165,10 +165,12 @@ - (void)hostSessionPinProvided:(NSNotification*)notification { NSString* pin = [[notification userInfo] objectForKey:kHostSessionPin]; if (_secretFetchedCallback) { + remoting::protocol::SecretFetchedCallback callback = _secretFetchedCallback; _runtime->network_task_runner()->PostTask( FROM_HERE, base::BindBlockArc(^{ - _secretFetchedCallback.Run(base::SysNSStringToUTF8(pin)); + callback.Run(base::SysNSStringToUTF8(pin)); })); + _secretFetchedCallback.Reset(); } } @@ -192,34 +194,69 @@ error:(remoting::protocol::ErrorCode)error { switch (state) { case remoting::protocol::ConnectionToHost::INITIALIZING: - NSLog(@"State --> INITIALIZING"); _sessionDetails.state = SessionInitializing; break; case remoting::protocol::ConnectionToHost::CONNECTING: - NSLog(@"State --> CONNECTING"); _sessionDetails.state = SessionConnecting; break; case remoting::protocol::ConnectionToHost::AUTHENTICATED: - NSLog(@"State --> AUTHENTICATED"); _sessionDetails.state = SessionAuthenticated; break; case remoting::protocol::ConnectionToHost::CONNECTED: - NSLog(@"State --> CONNECTED"); _sessionDetails.state = SessionConnected; break; case remoting::protocol::ConnectionToHost::FAILED: - NSLog(@"State --> FAILED"); _sessionDetails.state = SessionFailed; break; case remoting::protocol::ConnectionToHost::CLOSED: - NSLog(@"State --> CLOSED"); _sessionDetails.state = SessionClosed; + [self disconnectFromHost]; break; default: LOG(ERROR) << "onConnectionState, unknown state: " << state; } - // TODO(nicholss): Send along the error code when we know what to do about it. + switch (error) { + case remoting::protocol::ErrorCode::OK: + _sessionDetails.error = SessionErrorOk; + break; + case remoting::protocol::ErrorCode::PEER_IS_OFFLINE: + _sessionDetails.error = SessionErrorPeerIsOffline; + break; + case remoting::protocol::ErrorCode::SESSION_REJECTED: + _sessionDetails.error = SessionErrorSessionRejected; + break; + case remoting::protocol::ErrorCode::INCOMPATIBLE_PROTOCOL: + _sessionDetails.error = SessionErrorIncompatibleProtocol; + break; + case remoting::protocol::ErrorCode::AUTHENTICATION_FAILED: + _sessionDetails.error = SessionErrorAuthenticationFailed; + break; + case remoting::protocol::ErrorCode::INVALID_ACCOUNT: + _sessionDetails.error = SessionErrorInvalidAccount; + break; + case remoting::protocol::ErrorCode::CHANNEL_CONNECTION_ERROR: + _sessionDetails.error = SessionErrorChannelConnectionError; + break; + case remoting::protocol::ErrorCode::SIGNALING_ERROR: + _sessionDetails.error = SessionErrorSignalingError; + break; + case remoting::protocol::ErrorCode::SIGNALING_TIMEOUT: + _sessionDetails.error = SessionErrorSignalingTimeout; + break; + case remoting::protocol::ErrorCode::HOST_OVERLOAD: + _sessionDetails.error = SessionErrorHostOverload; + break; + case remoting::protocol::ErrorCode::MAX_SESSION_LENGTH: + _sessionDetails.error = SessionErrorMaxSessionLength; + break; + case remoting::protocol::ErrorCode::HOST_CONFIGURATION_ERROR: + _sessionDetails.error = SessionErrorHostConfigurationError; + case remoting::protocol::ErrorCode::UNKNOWN_ERROR: + _sessionDetails.error = SessionErrorUnknownError; + break; + } + [[NSNotificationCenter defaultCenter] postNotificationName:kHostSessionStatusChanged object:self @@ -240,7 +277,7 @@ } - (void)setCapabilities:(NSString*)capabilities { - NSLog(@"TODO(nicholss): implement this, setCapabilities."); + NSLog(@"TODO(nicholss): implement this, setCapabilities. %@", capabilities); } - (void)handleExtensionMessageOfType:(NSString*)type
diff --git a/remoting/protocol/channel_multiplexer.cc b/remoting/protocol/channel_multiplexer.cc index 5331bc4..2fc2fb3 100644 --- a/remoting/protocol/channel_multiplexer.cc +++ b/remoting/protocol/channel_multiplexer.cc
@@ -97,8 +97,7 @@ DISALLOW_COPY_AND_ASSIGN(MuxChannel); }; -class ChannelMultiplexer::MuxSocket : public P2PStreamSocket, - public base::SupportsWeakPtr<MuxSocket> { +class ChannelMultiplexer::MuxSocket : public P2PStreamSocket { public: MuxSocket(MuxChannel* channel); ~MuxSocket() override; @@ -128,21 +127,20 @@ SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<MuxSocket> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(MuxSocket); }; - -ChannelMultiplexer::MuxChannel::MuxChannel( - ChannelMultiplexer* multiplexer, - const std::string& name, - int send_id) +ChannelMultiplexer::MuxChannel::MuxChannel(ChannelMultiplexer* multiplexer, + const std::string& name, + int send_id) : multiplexer_(multiplexer), name_(name), send_id_(send_id), id_sent_(false), receive_id_(kChannelIdUnknown), - socket_(nullptr) { -} + socket_(nullptr) {} ChannelMultiplexer::MuxChannel::~MuxChannel() { // Socket must be destroyed before the channel. @@ -212,8 +210,8 @@ : channel_(channel), read_buffer_size_(0), write_pending_(false), - write_result_(0) { -} + write_result_(0), + weak_factory_(this) {} ChannelMultiplexer::MuxSocket::~MuxSocket() { channel_->OnSocketDestroyed(); @@ -252,8 +250,9 @@ packet->mutable_data()->assign(buffer->data(), size); write_pending_ = true; - channel_->DoWrite(std::move(packet), base::Bind( - &ChannelMultiplexer::MuxSocket::OnWriteComplete, AsWeakPtr())); + channel_->DoWrite(std::move(packet), + base::Bind(&ChannelMultiplexer::MuxSocket::OnWriteComplete, + weak_factory_.GetWeakPtr())); // OnWriteComplete() might be called above synchronously. if (write_pending_) {
diff --git a/remoting/signaling/iq_sender.cc b/remoting/signaling/iq_sender.cc index efa2528..1e6b494 100644 --- a/remoting/signaling/iq_sender.cc +++ b/remoting/signaling/iq_sender.cc
@@ -130,12 +130,13 @@ return true; } -IqRequest::IqRequest(IqSender* sender, const IqSender::ReplyCallback& callback, +IqRequest::IqRequest(IqSender* sender, + const IqSender::ReplyCallback& callback, const std::string& addressee) : sender_(sender), callback_(callback), - addressee_(addressee) { -} + addressee_(addressee), + weak_factory_(this) {} IqRequest::~IqRequest() { sender_->RemoveRequest(this); @@ -143,7 +144,8 @@ void IqRequest::SetTimeout(base::TimeDelta timeout) { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&IqRequest::OnTimeout, AsWeakPtr()), timeout); + FROM_HERE, base::Bind(&IqRequest::OnTimeout, weak_factory_.GetWeakPtr()), + timeout); } void IqRequest::CallCallback(const buzz::XmlElement* stanza) { @@ -160,8 +162,9 @@ // want to do that, so we post task to invoke the callback later. std::unique_ptr<buzz::XmlElement> stanza_copy(new buzz::XmlElement(*stanza)); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&IqRequest::DeliverResponse, AsWeakPtr(), - base::Passed(&stanza_copy))); + FROM_HERE, + base::Bind(&IqRequest::DeliverResponse, weak_factory_.GetWeakPtr(), + base::Passed(&stanza_copy))); } void IqRequest::DeliverResponse(std::unique_ptr<buzz::XmlElement> stanza) {
diff --git a/remoting/signaling/iq_sender.h b/remoting/signaling/iq_sender.h index be7c986..a1998f7 100644 --- a/remoting/signaling/iq_sender.h +++ b/remoting/signaling/iq_sender.h
@@ -78,7 +78,7 @@ }; // This call must only be used on the thread it was created on. -class IqRequest : public base::SupportsWeakPtr<IqRequest> { +class IqRequest { public: IqRequest(IqSender* sender, const IqSender::ReplyCallback& callback, const std::string& addressee); @@ -103,6 +103,8 @@ IqSender::ReplyCallback callback_; std::string addressee_; + base::WeakPtrFactory<IqRequest> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(IqRequest); };
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc index 1491273..15a9bf2 100644 --- a/remoting/test/protocol_perftest.cc +++ b/remoting/test/protocol_perftest.cc
@@ -318,7 +318,7 @@ host_pin_hash, nullptr); host_->SetAuthenticatorFactory(std::move(auth_factory)); - host_->AddStatusObserver(this); + host_->status_monitor()->AddStatusObserver(this); host_->Start(kHostOwner); message_loop_.task_runner()->PostTask(
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index e833e4d..dd0910ea 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn
@@ -221,6 +221,8 @@ "bpf_dsl/trap_registry.h", "seccomp-bpf-helpers/baseline_policy.cc", "seccomp-bpf-helpers/baseline_policy.h", + "seccomp-bpf-helpers/baseline_policy_android.cc", + "seccomp-bpf-helpers/baseline_policy_android.h", "seccomp-bpf-helpers/sigsys_handlers.cc", "seccomp-bpf-helpers/sigsys_handlers.h", "seccomp-bpf-helpers/syscall_parameters_restrictions.cc",
diff --git a/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc similarity index 89% rename from content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc rename to sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc index aad26f63..761a292 100644 --- a/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.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 "content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h" +#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.h" #include <errno.h> #include <fcntl.h> @@ -28,7 +28,7 @@ using sandbox::bpf_dsl::Error; using sandbox::bpf_dsl::ResultExpr; -namespace content { +namespace sandbox { #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC O_CLOEXEC @@ -58,13 +58,12 @@ } // namespace -SandboxBPFBasePolicyAndroid::SandboxBPFBasePolicyAndroid() - : SandboxBPFBasePolicy(), - pid_(getpid()) {} +BaselinePolicyAndroid::BaselinePolicyAndroid() + : BaselinePolicy() {} -SandboxBPFBasePolicyAndroid::~SandboxBPFBasePolicyAndroid() {} +BaselinePolicyAndroid::~BaselinePolicyAndroid() {} -ResultExpr SandboxBPFBasePolicyAndroid::EvaluateSyscall(int sysno) const { +ResultExpr BaselinePolicyAndroid::EvaluateSyscall(int sysno) const { bool override_and_allow = false; switch (sysno) { @@ -150,13 +149,13 @@ // https://crbug.com/644759 if (sysno == __NR_rt_tgsigqueueinfo) { const Arg<pid_t> tgid(0); - return If(tgid == pid_, Allow()) + return If(tgid == policy_pid(), Allow()) .Else(Error(EPERM)); } // https://crbug.com/655299 if (sysno == __NR_clock_getres) { - return sandbox::RestrictClockID(); + return RestrictClockID(); } #if defined(__x86_64__) @@ -196,7 +195,7 @@ option == SO_RCVTIMEO, option == SO_REUSEADDR)), Allow()) - .Else(SandboxBPFBasePolicy::EvaluateSyscall(sysno)); + .Else(BaselinePolicy::EvaluateSyscall(sysno)); } #elif defined(__i386__) if (sysno == __NR_socketcall) { @@ -208,14 +207,14 @@ SYS_SETSOCKOPT, SYS_GETSOCKOPT), Allow()) - .Default(SandboxBPFBasePolicy::EvaluateSyscall(sysno)); + .Default(BaselinePolicy::EvaluateSyscall(sysno)); } #endif if (override_and_allow) return Allow(); - return SandboxBPFBasePolicy::EvaluateSyscall(sysno); + return BaselinePolicy::EvaluateSyscall(sysno); } -} // namespace content +} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.h b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.h new file mode 100644 index 0000000..77fdedf --- /dev/null +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.h
@@ -0,0 +1,41 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BASELINE_POLICY_ANDROID_H_ +#define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BASELINE_POLICY_ANDROID_H_ + +#include <sys/types.h> + +#include "base/macros.h" +#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h" +#include "sandbox/sandbox_export.h" + +namespace sandbox { + +// This class provides a Seccomp-BPF sandbox policy for programs that run +// in the Android Runtime (Java) environment. It builds upon the Linux +// BaselinePolicy, which would be suitable for Android shell-based programs, +// and adds allowances for the JVM. +// +// As with the Linux BaselinePolicy, the behavior is largely implementation +// defined. +// +// TODO(rsesek): This policy may currently have allowances for //content-level +// features. This needs an audit. https://crbug.com/739879 +class SANDBOX_EXPORT BaselinePolicyAndroid : public BaselinePolicy { + public: + BaselinePolicyAndroid(); + ~BaselinePolicyAndroid() override; + + // sandbox::BaselinePolicy: + sandbox::bpf_dsl::ResultExpr EvaluateSyscall( + int system_call_number) const override; + + private: + DISALLOW_COPY_AND_ASSIGN(BaselinePolicyAndroid); +}; + +} // namespace sandbox + +#endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BASELINE_POLICY_ANDROID_H_
diff --git a/services/identity/identity_manager.cc b/services/identity/identity_manager.cc index 627e21f..a63f51a4 100644 --- a/services/identity/identity_manager.cc +++ b/services/identity/identity_manager.cc
@@ -8,7 +8,6 @@ #include "base/time/time.h" #include "components/signin/core/browser/account_tracker_service.h" -#include "components/signin/core/browser/signin_manager_base.h" #include "google_apis/gaia/google_service_auth_error.h" namespace identity { @@ -79,10 +78,12 @@ base::Bind(&IdentityManager::OnConnectionError, base::Unretained(this))); token_service_->AddObserver(this); + signin_manager_->AddObserver(this); } IdentityManager::~IdentityManager() { token_service_->RemoveObserver(this); + signin_manager_->RemoveObserver(this); } void IdentityManager::GetPrimaryAccountInfo( @@ -135,13 +136,25 @@ } void IdentityManager::OnRefreshTokenAvailable(const std::string& account_id) { + OnAccountStateChange(account_id); +} + +void IdentityManager::GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) { + OnAccountStateChange(account_id); +} + +void IdentityManager::OnAccountStateChange(const std::string& account_id) { AccountInfo account_info = account_tracker_->GetAccountInfo(account_id); AccountState account_state = GetStateOfAccount(account_info); - if (account_state.is_primary_account) { + // Check whether the primary account is available and notify any waiting + // consumers if so. + if (account_state.is_primary_account && account_state.has_refresh_token) { DCHECK(!account_info.account_id.empty()); DCHECK(!account_info.email.empty()); DCHECK(!account_info.gaia.empty()); + for (auto&& callback : primary_account_available_callbacks_) { std::move(callback).Run(account_info, account_state); }
diff --git a/services/identity/identity_manager.h b/services/identity/identity_manager.h index fe49463..3b92c853 100644 --- a/services/identity/identity_manager.h +++ b/services/identity/identity_manager.h
@@ -8,18 +8,19 @@ #include "base/callback_list.h" #include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_manager_base.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/identity/public/cpp/account_state.h" #include "services/identity/public/cpp/scope_set.h" #include "services/identity/public/interfaces/identity_manager.mojom.h" class AccountTrackerService; -class SigninManagerBase; namespace identity { class IdentityManager : public mojom::IdentityManager, - public OAuth2TokenService::Observer { + public OAuth2TokenService::Observer, + public SigninManagerBase::Observer { public: static void Create(mojom::IdentityManagerRequest request, AccountTrackerService* account_tracker, @@ -82,6 +83,14 @@ // OAuth2TokenService::Observer: void OnRefreshTokenAvailable(const std::string& account_id) override; + // SigninManagerBase::Observer: + void GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) override; + + // Notified when there is a change in the state of the account + // corresponding to |account_id|. + void OnAccountStateChange(const std::string& account_id); + // Deletes |request|. void AccessTokenRequestCompleted(AccessTokenRequest* request);
diff --git a/services/identity/identity_manager_unittest.cc b/services/identity/identity_manager_unittest.cc index 1fdb055d..6a3e7a5d 100644 --- a/services/identity/identity_manager_unittest.cc +++ b/services/identity/identity_manager_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/run_loop.h" +#include "build/build_config.h" #include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" @@ -23,6 +24,12 @@ namespace identity { namespace { +#if defined(OS_CHROMEOS) +using SigninManagerForTest = FakeSigninManagerBase; +#else +using SigninManagerForTest = FakeSigninManager; +#endif // OS_CHROMEOS + const std::string kTestGaiaId = "dummyId"; const std::string kTestEmail = "me@dummy.com"; const std::string kTestRefreshToken = "dummy-refresh-token"; @@ -81,7 +88,14 @@ IdentityManagerTest() : ServiceTest("identity_unittests", false), signin_client_(&pref_service_), +#if defined(OS_CHROMEOS) signin_manager_(&signin_client_, &account_tracker_) { +#else + signin_manager_(&signin_client_, + &token_service_, + &account_tracker_, + nullptr) { +#endif AccountTrackerService::RegisterPrefs(pref_service_.registry()); SigninManagerBase::RegisterProfilePrefs(pref_service_.registry()); SigninManagerBase::RegisterPrefs(pref_service_.registry()); @@ -162,7 +176,7 @@ sync_preferences::TestingPrefServiceSyncable pref_service_; AccountTrackerService account_tracker_; TestSigninClient signin_client_; - FakeSigninManagerBase signin_manager_; + SigninManagerForTest signin_manager_; FakeProfileOAuth2TokenService token_service_; DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest); @@ -335,6 +349,65 @@ EXPECT_TRUE(account_state.is_primary_account); } +// Check that GetPrimaryAccountWhenAvailable() returns the expected account info +// in the case where the token is available before the call is received but the +// account is made authenticated only *after* the call is received. This test is +// relevant only on non-ChromeOS platforms, as the flow being tested here is not +// possible on ChromeOS. +#if !defined(OS_CHROMEOS) +TEST_F(IdentityManagerTest, + GetPrimaryAccountWhenAvailableAuthenticationAvailableLater) { + AccountInfo account_info; + AccountState account_state; + + // Set the refresh token, but don't sign in yet. + std::string account_id_to_use = + account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail); + token_service()->UpdateCredentials(account_id_to_use, kTestRefreshToken); + base::RunLoop run_loop; + identity_manager_->GetPrimaryAccountWhenAvailable(base::Bind( + &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this), + run_loop.QuitClosure(), base::Unretained(&account_info), + base::Unretained(&account_state))); + + // Verify that the account is present and has a refresh token, but that the + // primary account is not yet considered available (this also serves to ensure + // that the preceding call has been received by the Identity Manager before + // proceeding). + base::RunLoop run_loop2; + identity_manager_->GetAccountInfoFromGaiaId( + kTestGaiaId, + base::Bind(&IdentityManagerTest::OnReceivedAccountInfoFromGaiaId, + base::Unretained(this), run_loop2.QuitClosure())); + run_loop2.Run(); + + EXPECT_TRUE(account_info_from_gaia_id_); + EXPECT_EQ(account_id_to_use, account_info_from_gaia_id_->account_id); + EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia); + EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email); + EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token); + EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account); + + EXPECT_TRUE(account_info.account_id.empty()); + + // Sign the user in and check that the callback is invoked as expected (i.e., + // the primary account is now considered available). Note that it is necessary + // to call SignIn() here to ensure that GoogleSigninSucceeded() is fired by + // the fake signin manager. + static_cast<FakeSigninManager*>(signin_manager()) + ->SignIn(kTestGaiaId, kTestEmail, "password"); + + run_loop.Run(); + + EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(), + account_info.account_id); + EXPECT_EQ(kTestGaiaId, account_info.gaia); + EXPECT_EQ(kTestEmail, account_info.email); + EXPECT_TRUE(account_state.has_refresh_token); + EXPECT_TRUE(account_state.is_primary_account); +} +#endif + // Check that GetPrimaryAccountWhenAvailable() returns the expected account // info to all callers in the case where the primary account is made available // after multiple overlapping calls have been received.
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h index 1aadef76..fcefa5b 100644 --- a/services/metrics/public/cpp/ukm_recorder.h +++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -21,6 +21,7 @@ class ContextualSearchRankerLoggerImpl; class PluginInfoMessageFilter; class UkmPageLoadMetricsObserver; +class LocalNetworkRequestsPageLoadMetricsObserver; namespace autofill { class AutofillMetrics; @@ -90,6 +91,7 @@ friend ContextualSearchRankerLoggerImpl; friend PluginInfoMessageFilter; friend UkmPageLoadMetricsObserver; + friend LocalNetworkRequestsPageLoadMetricsObserver; friend translate::TranslateRankerImpl; friend TestRecordingHelper; friend UkmInterface;
diff --git a/services/resource_coordinator/BUILD.gn b/services/resource_coordinator/BUILD.gn index a947735..8c02a1c 100644 --- a/services/resource_coordinator/BUILD.gn +++ b/services/resource_coordinator/BUILD.gn
@@ -76,10 +76,14 @@ "coordination_unit/process_coordination_unit_impl_unittest.cc", "memory_instrumentation/coordinator_impl_unittest.cc", "memory_instrumentation/process_map_unittest.cc", + "public/cpp/memory_instrumentation/os_metrics_unittest.cc", "public/cpp/memory_instrumentation/process_metrics_memory_dump_provider_unittest.cc", "public/cpp/tracing/chrome_trace_event_agent_unittest.cc", "tracing/agent_registry_unittest.cc", + "tracing/coordinator_unittest.cc", "tracing/recorder_unittest.cc", + "tracing/test_util.cc", + "tracing/test_util.h", ] if (!is_android) {
diff --git a/services/resource_coordinator/public/cpp/BUILD.gn b/services/resource_coordinator/public/cpp/BUILD.gn index e26cb413..b98ca1a 100644 --- a/services/resource_coordinator/public/cpp/BUILD.gn +++ b/services/resource_coordinator/public/cpp/BUILD.gn
@@ -12,6 +12,11 @@ "memory_instrumentation/coordinator.h", "memory_instrumentation/memory_instrumentation.cc", "memory_instrumentation/memory_instrumentation.h", + "memory_instrumentation/os_metrics.cc", + "memory_instrumentation/os_metrics.h", + "memory_instrumentation/os_metrics_linux.cc", + "memory_instrumentation/os_metrics_mac.cc", + "memory_instrumentation/os_metrics_win.cc", "memory_instrumentation/process_metrics_memory_dump_provider.cc", "memory_instrumentation/process_metrics_memory_dump_provider.h", "resource_coordinator_features.cc", @@ -22,6 +27,12 @@ "tracing/chrome_trace_event_agent.h", ] + if (is_android) { + set_sources_assignment_filter([]) + sources += [ "memory_instrumentation/os_metrics_linux.cc" ] + set_sources_assignment_filter(sources_assignment_filter) + } + defines = [ "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_IMPLEMENTATION" ] deps = [
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc new file mode 100644 index 0000000..6e4c92a --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
@@ -0,0 +1,15 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" + +namespace memory_instrumentation { + +mojom::RawOSMemDumpPtr GetOSMemoryDump(base::ProcessId pid) { + mojom::RawOSMemDumpPtr dump = mojom::RawOSMemDump::New(); + FillOSMemoryDump(pid, dump.get()); + return dump; +} + +} // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h new file mode 100644 index 0000000..09e258ec --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
@@ -0,0 +1,20 @@ +// 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 SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_OS_METRICS_H_ +#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_OS_METRICS_H_ + +#include "base/process/process_handle.h" +#include "services/resource_coordinator/public/cpp/resource_coordinator_export.h" +#include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" + +namespace memory_instrumentation { + +mojom::RawOSMemDumpPtr SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT +GetOSMemoryDump(base::ProcessId pid); + +void FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump); + +} // namespace memory_instrumentation + +#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_OS_METRICS_H_
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc new file mode 100644 index 0000000..e818bea --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
@@ -0,0 +1,83 @@ +// 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 <fcntl.h> +#include <stdint.h> +#include <memory> + +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" +#include "base/format_macros.h" +#include "base/process/process_metrics.h" +#include "base/strings/string_number_conversions.h" +#include "build/build_config.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" + +namespace memory_instrumentation { + +namespace { + +const uint32_t kMaxLineSize = 4096; + +base::ScopedFD OpenStatm(base::ProcessId pid) { + std::string name = + "/proc/" + + (pid == base::kNullProcessId ? "self" : base::IntToString(pid)) + + "/statm"; + base::ScopedFD fd = base::ScopedFD(open(name.c_str(), O_RDONLY)); + DCHECK(fd.is_valid()); + return fd; +} + +bool GetResidentAndSharedPagesFromStatmFile(int fd, + uint64_t* resident_pages, + uint64_t* shared_pages) { + lseek(fd, 0, SEEK_SET); + char line[kMaxLineSize]; + int res = read(fd, line, kMaxLineSize - 1); + if (res <= 0) + return false; + line[res] = '\0'; + int num_scanned = + sscanf(line, "%*s %" SCNu64 " %" SCNu64, resident_pages, shared_pages); + return num_scanned == 2; +} + +std::unique_ptr<base::ProcessMetrics> CreateProcessMetrics( + base::ProcessId pid) { + if (pid == base::kNullProcessId) { + return base::ProcessMetrics::CreateCurrentProcessMetrics(); + } + return base::ProcessMetrics::CreateProcessMetrics(pid); +} + +} // namespace + +void FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump) { + base::ScopedFD autoclose = OpenStatm(pid); + int statm_fd = autoclose.get(); + + if (statm_fd == -1) + return; + + uint64_t resident_pages; + uint64_t shared_pages; + bool success = GetResidentAndSharedPagesFromStatmFile( + statm_fd, &resident_pages, &shared_pages); + + if (!success) + return; + + auto process_metrics = CreateProcessMetrics(pid); + + const static size_t page_size = base::GetPageSize(); + uint64_t rss_anon_bytes = (resident_pages - shared_pages) * page_size; + uint64_t vm_swap_bytes = (resident_pages - shared_pages) * page_size; + + dump->platform_private_footprint.rss_anon_bytes = rss_anon_bytes; + dump->platform_private_footprint.vm_swap_bytes = vm_swap_bytes; + dump->resident_set_kb = process_metrics->GetWorkingSetSize() / 1024; +} + +} // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc new file mode 100644 index 0000000..a418e861 --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc
@@ -0,0 +1,32 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" + +#include "base/process/process_metrics.h" + +namespace memory_instrumentation { + +void FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump) { + // Creating process metrics for child processes in mac or windows requires + // additional information like ProcessHandle or port provider. + DCHECK_EQ(base::kNullProcessId, pid); + auto process_metrics = base::ProcessMetrics::CreateCurrentProcessMetrics(); + + size_t private_bytes; + size_t shared_bytes; + size_t resident_bytes; + size_t locked_bytes; + if (!process_metrics->GetMemoryBytes(&private_bytes, &shared_bytes, + &resident_bytes, &locked_bytes)) { + return; + } + base::ProcessMetrics::TaskVMInfo info = process_metrics->GetTaskVMInfo(); + dump->platform_private_footprint.phys_footprint_bytes = info.phys_footprint; + dump->platform_private_footprint.internal_bytes = info.internal; + dump->platform_private_footprint.compressed_bytes = info.compressed; + dump->resident_set_kb = resident_bytes / 1024; +} + +} // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc new file mode 100644 index 0000000..61cabc4 --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
@@ -0,0 +1,24 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" + +#include "base/process/process_handle.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace memory_instrumentation { + +TEST(OSMetricsTest, GivesNonZeroResults) { + base::ProcessId pid = base::kNullProcessId; + mojom::RawOSMemDumpPtr dump = GetOSMemoryDump(pid); +#if defined(OS_LINUX) || defined(OS_ANDROID) + EXPECT_GT(dump->platform_private_footprint.rss_anon_bytes, 0u); +#elif defined(OS_WIN) + EXPECT_GT(dump->platform_private_footprint.private_bytes, 0u); +#elif defined(OS_MACOSX) + EXPECT_GT(dump->platform_private_footprint.internal_bytes, 0u); +#endif +} + +} // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc new file mode 100644 index 0000000..feef20d3f --- /dev/null +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc
@@ -0,0 +1,23 @@ +// 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 "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" + +#include "base/process/process_metrics.h" + +namespace memory_instrumentation { + +void FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump) { + // Creating process metrics for child processes in mac or windows requires + // additional information like ProcessHandle or port provider. + DCHECK_EQ(base::kNullProcessId, pid); + auto process_metrics = base::ProcessMetrics::CreateCurrentProcessMetrics(); + + size_t private_bytes = 0; + process_metrics->GetMemoryBytes(&private_bytes, nullptr); + dump->platform_private_footprint.private_bytes = private_bytes; + dump->resident_set_kb = process_metrics->GetWorkingSetSize() / 1024; +} + +} // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.cc index d948b7b8..f6c73328 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.cc
@@ -23,6 +23,7 @@ #include "base/trace_event/process_memory_maps.h" #include "base/trace_event/process_memory_totals.h" #include "build/build_config.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" #if defined(OS_MACOSX) #include <libproc.h> @@ -181,20 +182,6 @@ return num_valid_regions; } -bool GetResidentAndSharedPagesFromStatmFile(int fd, - uint64_t* resident_pages, - uint64_t* shared_pages) { - lseek(fd, 0, SEEK_SET); - char line[kMaxLineSize]; - int res = read(fd, line, kMaxLineSize - 1); - if (res <= 0) - return false; - line[res] = '\0'; - int num_scanned = - sscanf(line, "%*s %" SCNu64 " %" SCNu64, resident_pages, shared_pages); - return num_scanned == 2; -} - #endif // defined(OS_LINUX) || defined(OS_ANDROID) std::unique_ptr<base::ProcessMetrics> CreateProcessMetrics( @@ -250,6 +237,18 @@ pmd->set_has_process_mmaps(); return res; } + +bool GetResidentPagesFromStatmFile(int fd, uint64_t* resident_pages) { + lseek(fd, 0, SEEK_SET); + char line[kMaxLineSize]; + int res = read(fd, line, kMaxLineSize - 1); + if (res <= 0) + return false; + line[res] = '\0'; + int num_scanned = sscanf(line, "%*s %" SCNu64, resident_pages); + return num_scanned == 1; +} + #endif // defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_WIN) @@ -612,6 +611,22 @@ bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals( const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { +// On Windows add extra region if necessary: +#if defined(OS_WIN) + if (args.level_of_detail == + base::trace_event::MemoryDumpLevelOfDetail::DETAILED) { + uint64_t pss_bytes = 0; + bool res = process_metrics_->GetProportionalSetSizeBytes(&pss_bytes); + if (res) { + base::trace_event::ProcessMemoryMaps::VMRegion region; + region.byte_stats_proportional_resident = pss_bytes; + pmd->process_mmaps()->AddVMRegion(region); + pmd->set_has_process_mmaps(); + } + } +#endif // defined(OS_WIN) + +// On Mac set a few extra values on process_totals: #if defined(OS_MACOSX) size_t private_bytes; size_t shared_bytes; @@ -621,66 +636,30 @@ &resident_bytes, &locked_bytes)) { return false; } - uint64_t rss_bytes = resident_bytes; pmd->process_totals()->SetExtraFieldInBytes("private_bytes", private_bytes); pmd->process_totals()->SetExtraFieldInBytes("shared_bytes", shared_bytes); pmd->process_totals()->SetExtraFieldInBytes("locked_bytes", locked_bytes); - - base::trace_event::ProcessMemoryTotals::PlatformPrivateFootprint footprint; - base::ProcessMetrics::TaskVMInfo info = process_metrics_->GetTaskVMInfo(); - footprint.phys_footprint_bytes = info.phys_footprint; - footprint.internal_bytes = info.internal; - footprint.compressed_bytes = info.compressed; - - pmd->process_totals()->SetPlatformPrivateFootprint(footprint); -#else - uint64_t rss_bytes = process_metrics_->GetWorkingSetSize(); #endif // defined(OS_MACOSX) - if (rss_bytes_for_testing) + + mojom::RawOSMemDumpPtr dump = GetOSMemoryDump(process_); + + uint64_t rss_bytes = dump->resident_set_kb * 1024; + if (rss_bytes_for_testing) { rss_bytes = rss_bytes_for_testing; - - // rss_bytes will be 0 if the process ended while dumping. - if (!rss_bytes) - return false; - - uint64_t peak_rss_bytes = 0; - -#if defined(OS_LINUX) || defined(OS_ANDROID) - base::trace_event::ProcessMemoryTotals::PlatformPrivateFootprint footprint; - - base::ScopedFD autoclose; - int statm_fd = fast_polling_statm_fd_.get(); - if (statm_fd == -1) { - autoclose = OpenStatm(); - statm_fd = autoclose.get(); } - if (statm_fd == -1) - return false; - const static size_t page_size = base::GetPageSize(); - uint64_t resident_pages; - uint64_t shared_pages; - bool success = GetResidentAndSharedPagesFromStatmFile( - statm_fd, &resident_pages, &shared_pages); - if (!success) - return false; - footprint.rss_anon_bytes = (resident_pages - shared_pages) * page_size; - footprint.vm_swap_bytes = process_metrics_->GetVmSwapBytes(); - pmd->process_totals()->SetPlatformPrivateFootprint(footprint); -#endif // defined(OS_LINUX) || defined(OS_ANDROID) - -#if defined(OS_WIN) - { - size_t private_bytes; - base::trace_event::ProcessMemoryTotals::PlatformPrivateFootprint footprint; - process_metrics_->GetMemoryBytes(&private_bytes, nullptr); - footprint.private_bytes = private_bytes; - pmd->process_totals()->SetPlatformPrivateFootprint(footprint); + // resident set size will be 0 if the process ended while dumping. + if (rss_bytes == 0u) { + return false; } -#endif -#if !defined(OS_IOS) - peak_rss_bytes = process_metrics_->GetPeakWorkingSetSize(); + pmd->process_totals()->set_resident_set_bytes(rss_bytes); + pmd->process_totals()->SetPlatformPrivateFootprint( + dump->platform_private_footprint); + pmd->set_has_process_totals(); + pmd->process_totals()->set_peak_resident_set_bytes(GetPeakResidentSetBytes()); + +// On Linux and Android reset rss peak if necessary #if defined(OS_LINUX) || defined(OS_ANDROID) if (is_rss_peak_resettable_) { std::string clear_refs_file = @@ -698,30 +677,20 @@ } close(clear_refs_fd); } -#elif defined(OS_WIN) - if (args.level_of_detail == - base::trace_event::MemoryDumpLevelOfDetail::DETAILED) { - uint64_t pss_bytes = 0; - bool res = process_metrics_->GetProportionalSetSizeBytes(&pss_bytes); - if (res) { - base::trace_event::ProcessMemoryMaps::VMRegion region; - region.byte_stats_proportional_resident = pss_bytes; - pmd->process_mmaps()->AddVMRegion(region); - pmd->set_has_process_mmaps(); - } - } - #endif -#endif // !defined(OS_IOS) - - pmd->process_totals()->set_resident_set_bytes(rss_bytes); - pmd->set_has_process_totals(); - pmd->process_totals()->set_peak_resident_set_bytes(peak_rss_bytes); // Returns true even if other metrics failed, since rss is reported. return true; } +uint64_t ProcessMetricsMemoryDumpProvider::GetPeakResidentSetBytes() { +#if defined(OS_IOS) + return 0u; +#else + return process_metrics_->GetPeakWorkingSetSize(); +#endif +} + #if defined(OS_LINUX) || defined(OS_ANDROID) base::ScopedFD ProcessMetricsMemoryDumpProvider::OpenStatm() { std::string name = @@ -750,9 +719,7 @@ } uint64_t resident_pages = 0; - uint64_t ignored_shared_pages = 0; - if (!GetResidentAndSharedPagesFromStatmFile(statm_fd, &resident_pages, - &ignored_shared_pages)) + if (!GetResidentPagesFromStatmFile(statm_fd, &resident_pages)) return; static size_t page_size = base::GetPageSize();
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.h b/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.h index 1489845..c0de92f 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.h +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider.h
@@ -13,6 +13,7 @@ #include "base/trace_event/memory_dump_provider.h" #include "build/build_config.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_export.h" +#include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" namespace base { class ProcessMetrics; @@ -66,6 +67,7 @@ base::trace_event::ProcessMemoryDump* pmd); bool DumpProcessMemoryMaps(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd); + uint64_t GetPeakResidentSetBytes(); static uint64_t rss_bytes_for_testing; static FactoryFunction factory_for_testing;
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider_unittest.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider_unittest.cc index a9c32497..b997757 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider_unittest.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/process_metrics_memory_dump_provider_unittest.cc
@@ -17,6 +17,7 @@ #include "base/trace_event/process_memory_maps.h" #include "base/trace_event/process_memory_totals.h" #include "base/trace_event/trace_event_argument.h" +#include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_MACOSX) @@ -411,4 +412,5 @@ } #endif // defined(OS_MACOSX) + } // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.cc b/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.cc index 706cc4b..fa5ff37 100644 --- a/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.cc +++ b/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.cc
@@ -30,9 +30,7 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!g_chrome_trace_event_agent); g_chrome_trace_event_agent = this; - // agent_registry can be null in tests. The constructor is private and cannot - // be directly used in non-test scenarios. GetOrCreateInstance makes sure that - // the constructor is called with a non-null agent_registry. + // agent_registry can be null in tests. if (!agent_registry) return; @@ -55,10 +53,8 @@ } void ChromeTraceEventAgent::StartTracing(const std::string& config, - mojom::RecorderPtr recorder, const StartTracingCallback& callback) { DCHECK(!recorder_); - recorder_ = std::move(recorder); if (!base::trace_event::TraceLog::GetInstance()->IsEnabled()) { base::trace_event::TraceLog::GetInstance()->SetEnabled( base::trace_event::TraceConfig(config), @@ -67,10 +63,10 @@ callback.Run(); } -void ChromeTraceEventAgent::StopAndFlush() { +void ChromeTraceEventAgent::StopAndFlush(mojom::RecorderPtr recorder) { + DCHECK(!recorder_); + recorder_ = std::move(recorder); base::trace_event::TraceLog::GetInstance()->SetDisabled(); - if (!recorder_) - return; for (const auto& generator : metadata_generator_functions_) { auto metadata = generator.Run(); if (metadata)
diff --git a/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.h b/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.h index 8e8fe475..f8213186 100644 --- a/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.h +++ b/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent.h
@@ -27,20 +27,20 @@ static ChromeTraceEventAgent* GetInstance(); + explicit ChromeTraceEventAgent(mojom::AgentRegistryPtr agent_registry); + void AddMetadataGeneratorFunction(MetadataGeneratorFunction generator); private: friend std::default_delete<ChromeTraceEventAgent>; // For Testing friend class ChromeTraceEventAgentTest; // For Testing - explicit ChromeTraceEventAgent(mojom::AgentRegistryPtr agent_registry); ~ChromeTraceEventAgent() override; // mojom::Agent void StartTracing(const std::string& config, - mojom::RecorderPtr recorder, const StartTracingCallback& callback) override; - void StopAndFlush() override; + void StopAndFlush(mojom::RecorderPtr recorder) override; void RequestClockSyncMarker( const std::string& sync_id, const RequestClockSyncMarkerCallback& callback) override;
diff --git a/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent_unittest.cc b/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent_unittest.cc index b7ca96ec..bb71454 100644 --- a/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent_unittest.cc +++ b/services/resource_coordinator/public/cpp/tracing/chrome_trace_event_agent_unittest.cc
@@ -89,17 +89,19 @@ message_loop_.reset(); } - void StartTracing(const std::string& categories, base::Closure quit_closure) { + void StartTracing(const std::string& categories) { + agent_->StartTracing( + base::trace_event::TraceConfig(categories, "").ToString(), + base::BindRepeating([] {})); + } + + void StopAndFlush(base::Closure quit_closure) { mojom::RecorderPtr recorder_ptr; recorder_.reset(new MockRecorder(MakeRequest(&recorder_ptr))); recorder_->set_quit_closure(quit_closure); - agent_->StartTracing( - base::trace_event::TraceConfig(categories, "").ToString(), - std::move(recorder_ptr), base::BindRepeating([] {})); + agent_->StopAndFlush(std::move(recorder_ptr)); } - void StopAndFlush() { agent_->StopAndFlush(); } - void AddMetadataGeneratorFunction( ChromeTraceEventAgent::MetadataGeneratorFunction generator) { agent_->AddMetadataGeneratorFunction(generator); @@ -130,19 +132,19 @@ TEST_F(ChromeTraceEventAgentTest, StartTracing) { EXPECT_FALSE(base::trace_event::TraceLog::GetInstance()->IsEnabled()); base::RunLoop run_loop; - StartTracing("*", run_loop.QuitClosure()); + StartTracing("*"); EXPECT_TRUE(base::trace_event::TraceLog::GetInstance()->IsEnabled()); - StopAndFlush(); + StopAndFlush(run_loop.QuitClosure()); run_loop.Run(); } TEST_F(ChromeTraceEventAgentTest, StopAndFlushEvents) { EXPECT_FALSE(base::trace_event::TraceLog::GetInstance()->IsEnabled()); base::RunLoop run_loop; - StartTracing(kTestCategory, run_loop.QuitClosure()); + StartTracing(kTestCategory); TRACE_EVENT_INSTANT0(kTestCategory, "event1", TRACE_EVENT_SCOPE_THREAD); TRACE_EVENT_INSTANT0(kTestCategory, "event2", TRACE_EVENT_SCOPE_THREAD); - StopAndFlush(); + StopAndFlush(run_loop.QuitClosure()); run_loop.Run(); auto* mock_recorder = recorder(); @@ -167,8 +169,8 @@ metadata_dict->SetString(kTestMetadataKey, "test metadata"); return metadata_dict; })); - StartTracing(kTestCategory, run_loop.QuitClosure()); - StopAndFlush(); + StartTracing(kTestCategory); + StopAndFlush(run_loop.QuitClosure()); run_loop.Run(); auto* mock_recorder = recorder();
diff --git a/services/resource_coordinator/public/interfaces/BUILD.gn b/services/resource_coordinator/public/interfaces/BUILD.gn index a11ab082..33587e1 100644 --- a/services/resource_coordinator/public/interfaces/BUILD.gn +++ b/services/resource_coordinator/public/interfaces/BUILD.gn
@@ -16,6 +16,7 @@ "service_callbacks.mojom", "service_constants.mojom", "tracing/tracing.mojom", + "tracing/tracing_constants.mojom", ] public_deps = [
diff --git a/services/resource_coordinator/public/interfaces/tracing/tracing.mojom b/services/resource_coordinator/public/interfaces/tracing/tracing.mojom index a102cca..f56022b 100644 --- a/services/resource_coordinator/public/interfaces/tracing/tracing.mojom +++ b/services/resource_coordinator/public/interfaces/tracing/tracing.mojom
@@ -31,12 +31,12 @@ }; // When the tracing service calls |StopAndFlush| on an agent, the agent begins -// serializing data into the recorder that was given in the |StartTracing| call. -// When finished, the agent should close the recorder connection to signal the -// tracing service that no more data will be sent. +// serializing data into the given recorder. When finished, the agent should +// close the recorder connection to signal the tracing service that no more data +// will be sent. interface Agent { - StartTracing(string config, Recorder recorder) => (); - StopAndFlush(); + StartTracing(string config) => (); + StopAndFlush(Recorder recorder); RequestClockSyncMarker(string sync_id) => ( mojo.common.mojom.TimeTicks issue_ts, mojo.common.mojom.TimeTicks issue_end_ts); @@ -57,10 +57,13 @@ // from all registered agents. At any given time, there should be at most one // connected controller. interface Coordinator { - StartTracing(handle<data_pipe_producer> stream, string config); - StopAndFlush(); + // The return value is false if tracing is already enabled with a different + // config. Otherwise, true is returned as soon as the service receives acks + // from all existing agents and agents that connect during |StartTracing|. + StartTracing(string config) => (bool success); + StopAndFlush(handle<data_pipe_producer> stream); IsTracing() => (bool is_tracing); RequestBufferUsage() => (bool success, float percent_full, uint32 approximate_count); - GetCategories() => (string categories); + GetCategories() => (bool success, string categories); };
diff --git a/services/resource_coordinator/public/interfaces/tracing/tracing_constants.mojom b/services/resource_coordinator/public/interfaces/tracing/tracing_constants.mojom new file mode 100644 index 0000000..dc04c8c --- /dev/null +++ b/services/resource_coordinator/public/interfaces/tracing/tracing_constants.mojom
@@ -0,0 +1,7 @@ +// 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. + +module tracing.mojom; + +const uint32 kStopTracingRetryTimeMilliseconds = 100;
diff --git a/services/resource_coordinator/tracing/BUILD.gn b/services/resource_coordinator/tracing/BUILD.gn index e578dfcd..a4182cc5 100644 --- a/services/resource_coordinator/tracing/BUILD.gn +++ b/services/resource_coordinator/tracing/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "agent_registry.cc", "agent_registry.h", + "coordinator.cc", + "coordinator.h", "recorder.cc", "recorder.h", ]
diff --git a/services/resource_coordinator/tracing/agent_registry.cc b/services/resource_coordinator/tracing/agent_registry.cc index d87a055..b7a2712 100644 --- a/services/resource_coordinator/tracing/agent_registry.cc +++ b/services/resource_coordinator/tracing/agent_registry.cc
@@ -37,25 +37,30 @@ AgentRegistry::AgentEntry::~AgentEntry() = default; -void AgentRegistry::AgentEntry::SetDisconnectClosure( +void AgentRegistry::AgentEntry::AddDisconnectClosure( + const void* closure_name, base::OnceClosure closure) { - DCHECK(closure_.is_null()); - closure_ = std::move(closure); + DCHECK_EQ(0u, closures_.count(closure_name)); + closures_[closure_name] = std::move(closure); } -bool AgentRegistry::AgentEntry::RemoveDisconnectClosure() { - bool closure_was_set = !closure_.is_null(); - closure_.Reset(); - return closure_was_set; +bool AgentRegistry::AgentEntry::RemoveDisconnectClosure( + const void* closure_name) { + return closures_.erase(closure_name) > 0; +} + +bool AgentRegistry::AgentEntry::HasDisconnectClosure(const void* closure_name) { + return closures_.count(closure_name) > 0; } void AgentRegistry::AgentEntry::OnConnectionError() { - // Run the disconnect closure if it is set. We should mark |closure_| as - // movable so that the version of |Run| that takes an rvalue reference is + // Run disconnect closures if there is any. We should mark |key_value.second| + // as movable so that the version of |Run| that takes an rvalue reference is // selected not the version that takes a const reference. The former is for // once callbacks and the latter is for repeating callbacks. - if (!closure_.is_null()) - std::move(closure_).Run(); + for (auto& key_value : closures_) { + std::move(key_value.second).Run(); + } agent_registry_->UnregisterAgent(id_); } @@ -95,6 +100,15 @@ agent_initialization_callback_.Reset(); } +bool AgentRegistry::HasDisconnectClosure(const void* closure_name) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + for (const auto& key_value : agents_) { + if (key_value.second->HasDisconnectClosure(closure_name)) + return true; + } + return false; +} + void AgentRegistry::RegisterAgent(mojom::AgentPtr agent, const std::string& label, mojom::TraceDataType type,
diff --git a/services/resource_coordinator/tracing/agent_registry.h b/services/resource_coordinator/tracing/agent_registry.h index 6841978c..970bd8d 100644 --- a/services/resource_coordinator/tracing/agent_registry.h +++ b/services/resource_coordinator/tracing/agent_registry.h
@@ -30,11 +30,13 @@ bool supports_explicit_clock_sync); ~AgentEntry(); - // Currently, at most one callback when the tracing agent is disconnected is - // enough. We can generalize this later if several parts of the service need - // to get notified when an agent disconnects. - void SetDisconnectClosure(base::OnceClosure closure); - bool RemoveDisconnectClosure(); + void AddDisconnectClosure(const void* closure_name, + base::OnceClosure closure); + bool RemoveDisconnectClosure(const void* closure_name); + bool HasDisconnectClosure(const void* closure_name); + size_t num_disconnect_closures_for_testing() const { + return closures_.size(); + } mojom::Agent* agent() const { return agent_.get(); } const std::string& label() const { return label_; } @@ -52,7 +54,7 @@ const std::string label_; const mojom::TraceDataType type_; const bool supports_explicit_clock_sync_; - base::OnceClosure closure_; + std::map<const void*, base::OnceClosure> closures_; DISALLOW_COPY_AND_ASSIGN(AgentEntry); }; @@ -71,6 +73,7 @@ void SetAgentInitializationCallback( const AgentInitializationCallback& callback); void RemoveAgentInitializationCallback(); + bool HasDisconnectClosure(const void* closure_name); template <typename FunctionType> void ForAllAgents(FunctionType function) { @@ -83,6 +86,7 @@ private: friend std::default_delete<AgentRegistry>; friend class AgentRegistryTest; // For testing. + friend class CoordinatorTest; // For testing. ~AgentRegistry() override;
diff --git a/services/resource_coordinator/tracing/agent_registry_unittest.cc b/services/resource_coordinator/tracing/agent_registry_unittest.cc index c356e680..3493ee2 100644 --- a/services/resource_coordinator/tracing/agent_registry_unittest.cc +++ b/services/resource_coordinator/tracing/agent_registry_unittest.cc
@@ -10,38 +10,12 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "mojo/public/cpp/bindings/binding.h" #include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h" +#include "services/resource_coordinator/tracing/test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace tracing { -class MockAgent : public mojom::Agent { - public: - MockAgent() : binding_(this) {} - - mojom::AgentPtr CreateAgentPtr() { - mojom::AgentPtr agent; - binding_.Bind(mojo::MakeRequest(&agent)); - return agent; - } - - private: - // mojom::Agent - void StartTracing(const std::string& config, - mojom::RecorderPtr recorder, - const StartTracingCallback& callback) override {} - void StopAndFlush() override {} - void RequestClockSyncMarker( - const std::string& sync_id, - const RequestClockSyncMarkerCallback& callback) override {} - void RequestBufferStatus( - const RequestBufferStatusCallback& callback) override {} - void GetCategories(const GetCategoriesCallback& callback) override {} - - mojo::Binding<mojom::Agent> binding_; -}; - class AgentRegistryTest : public testing::Test { public: void SetUp() override {
diff --git a/services/resource_coordinator/tracing/coordinator.cc b/services/resource_coordinator/tracing/coordinator.cc new file mode 100644 index 0000000..625cd80 --- /dev/null +++ b/services/resource_coordinator/tracing/coordinator.cc
@@ -0,0 +1,352 @@ +// 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 "services/resource_coordinator/tracing/coordinator.h" + +#include <algorithm> +#include <string> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback_forward.h" +#include "base/callback_helpers.h" +#include "base/json/json_writer.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/task_scheduler/post_task.h" +#include "base/task_scheduler/task_traits.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/trace_event/trace_config.h" +#include "mojo/common/data_pipe_utils.h" +#include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h" +#include "services/resource_coordinator/public/interfaces/tracing/tracing_constants.mojom.h" +#include "services/resource_coordinator/tracing/agent_registry.h" +#include "services/resource_coordinator/tracing/recorder.h" +#include "services/service_manager/public/cpp/bind_source_info.h" + +namespace { + +const char kMetadataTraceLabel[] = "metadata"; + +const char kStartTracingClosureName[] = "StartTracingClosure"; +const char kRequestBufferUsageClosureName[] = "RequestBufferUsageClosure"; +const char kGetCategoriesClosureName[] = "GetCategoriesClosure"; + +tracing::Coordinator* g_coordinator = nullptr; + +} // namespace + +namespace tracing { + +// static +Coordinator* Coordinator::GetInstance() { + DCHECK(g_coordinator); + return g_coordinator; +} + +Coordinator::Coordinator() + : binding_(this), + task_runner_(base::ThreadTaskRunnerHandle::Get()), + agent_registry_(AgentRegistry::GetInstance()) { + DCHECK(!g_coordinator); + DCHECK(agent_registry_); + g_coordinator = this; + constexpr base::TaskTraits traits = {base::MayBlock(), + base::WithBaseSyncPrimitives(), + base::TaskPriority::BACKGROUND}; + background_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(traits); +} + +Coordinator::~Coordinator() { + g_coordinator = nullptr; +} + +void Coordinator::BindCoordinatorRequest( + const service_manager::BindSourceInfo& source_info, + mojom::CoordinatorRequest request) { + binding_.Bind(std::move(request)); +} + +void Coordinator::StartTracing(const std::string& config, + const StartTracingCallback& callback) { + if (is_tracing_) { + // Cannot change the config while tracing is enabled. + callback.Run(config == config_); + return; + } + + is_tracing_ = true; + config_ = config; + agent_registry_->SetAgentInitializationCallback(base::BindRepeating( + &Coordinator::SendStartTracingToAgent, base::Unretained(this))); + if (!agent_registry_->HasDisconnectClosure(&kStartTracingClosureName)) { + callback.Run(true); + return; + } + start_tracing_callback_ = callback; +} + +void Coordinator::SendStartTracingToAgent( + AgentRegistry::AgentEntry* agent_entry) { + agent_entry->AddDisconnectClosure( + &kStartTracingClosureName, + base::BindOnce(&Coordinator::OnTracingStarted, base::Unretained(this), + base::Unretained(agent_entry))); + agent_entry->agent()->StartTracing( + config_, base::BindRepeating(&Coordinator::OnTracingStarted, + base::Unretained(this), + base::Unretained(agent_entry))); +} + +void Coordinator::OnTracingStarted(AgentRegistry::AgentEntry* agent_entry) { + bool removed = + agent_entry->RemoveDisconnectClosure(&kStartTracingClosureName); + DCHECK(removed); + + if (!agent_registry_->HasDisconnectClosure(&kStartTracingClosureName) && + !start_tracing_callback_.is_null()) { + base::ResetAndReturn(&start_tracing_callback_).Run(true); + } +} + +void Coordinator::StopAndFlush(mojo::ScopedDataPipeProducerHandle stream) { + DCHECK(is_tracing_); + DCHECK(!stream_.is_valid()); + DCHECK(stream.is_valid()); + + // Do not send |StartTracing| to agents that connect from now on. + agent_registry_->RemoveAgentInitializationCallback(); + stream_ = std::move(stream); + StopAndFlushInternal(); +} + +void Coordinator::StopAndFlushInternal() { + if (agent_registry_->HasDisconnectClosure(&kStartTracingClosureName)) { + // We received a |StopAndFlush| command before receiving |StartTracing| acks + // from all agents. Let's retry after a delay. + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindRepeating(&Coordinator::StopAndFlushInternal, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds( + mojom::kStopTracingRetryTimeMilliseconds)); + return; + } + + stream_header_written_ = false; + streaming_label_.clear(); + + agent_registry_->ForAllAgents([this](AgentRegistry::AgentEntry* agent_entry) { + bool data_is_array = agent_entry->type() == mojom::TraceDataType::ARRAY; + mojom::RecorderPtr ptr; + recorders_[agent_entry->label()].insert(base::MakeUnique<Recorder>( + MakeRequest(&ptr), data_is_array, + base::BindRepeating(&Coordinator::OnRecorderDataChange, + base::Unretained(this), agent_entry->label()), + background_task_runner_)); + DCHECK(data_is_array || recorders_[agent_entry->label()].size() == 1); + agent_entry->agent()->StopAndFlush(std::move(ptr)); + }); + + if (recorders_.empty()) + OnFlushDone(); +} + +void Coordinator::OnRecorderDataChange(const std::string& label) { + DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); + + // Bail out if we are in the middle of writing events for another label to the + // stream, since we do not want to interleave chunks for different fields. For + // example, we do not want to mix |traceEvent| chunks with |battor| chunks. + // + // If we receive a |battor| chunk from an agent while writing |traceEvent| + // chunks to the stream, we wait until all agents that send |traceEvent| + // chunks are done, and then, we start writing |battor| chunks. + if (!streaming_label_.empty() && streaming_label_ != label) + return; + + while (streaming_label_.empty() || !StreamEventsForCurrentLabel()) { + // We are not waiting for data from any particular label now. So, we look at + // the recorders that have some data available and select the next label to + // stream. + streaming_label_.clear(); + bool all_finished = true; + for (const auto& key_value : recorders_) { + for (const auto& recorder : key_value.second) { + all_finished &= !recorder->is_recording(); + if (!recorder->data().empty()) { + streaming_label_ = key_value.first; + json_field_name_written_ = false; + break; + } + } + if (!streaming_label_.empty()) + break; + } + + if (streaming_label_.empty()) { + // No recorder has any data for us, right now. + if (all_finished) { + StreamMetadata(); + if (stream_header_written_) + mojo::common::BlockingCopyFromString("}", stream_); + // Recorder connections should be closed on their binding thread. + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&Coordinator::OnFlushDone, base::Unretained(this))); + } + return; + } + } +} + +bool Coordinator::StreamEventsForCurrentLabel() { + DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); + bool waiting_for_agents = false; + bool data_is_array = (*recorders_[streaming_label_].begin())->data_is_array(); + for (const auto& recorder : recorders_[streaming_label_]) { + waiting_for_agents |= recorder->is_recording(); + if (recorder->data().empty()) + continue; + if (json_field_name_written_) { + if (data_is_array) + mojo::common::BlockingCopyFromString(",", stream_); + } else { + std::string prefix = stream_header_written_ ? ",\"" : "{\""; + prefix += streaming_label_ + "\":" + (data_is_array ? "[" : "\""); + mojo::common::BlockingCopyFromString(prefix, stream_); + json_field_name_written_ = true; + stream_header_written_ = true; + } + mojo::common::BlockingCopyFromString(recorder->data(), stream_); + recorder->clear_data(); + } + if (!waiting_for_agents) { + if (json_field_name_written_) + mojo::common::BlockingCopyFromString(data_is_array ? "]" : "\"", stream_); + } + return waiting_for_agents; +} + +void Coordinator::StreamMetadata() { + DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); + + base::DictionaryValue metadata; + for (const auto& key_value : recorders_) { + for (const auto& recorder : key_value.second) { + metadata.MergeDictionary(&(recorder->metadata())); + } + } + + std::string metadataJSON; + if (!metadata.empty() && base::JSONWriter::Write(metadata, &metadataJSON)) { + std::string prefix = stream_header_written_ ? ",\"" : "{\""; + mojo::common::BlockingCopyFromString( + prefix + std::string(kMetadataTraceLabel) + "\":" + metadataJSON, + stream_); + stream_header_written_ = true; + } +} + +void Coordinator::OnFlushDone() { + recorders_.clear(); + stream_.reset(); + is_tracing_ = false; +} + +void Coordinator::IsTracing(const IsTracingCallback& callback) { + callback.Run(is_tracing_); +} + +void Coordinator::RequestBufferUsage( + const RequestBufferUsageCallback& callback) { + if (!request_buffer_usage_callback_.is_null()) { + callback.Run(false, 0, 0); + return; + } + + maximum_trace_buffer_usage_ = 0; + approximate_event_count_ = 0; + request_buffer_usage_callback_ = callback; + agent_registry_->ForAllAgents([this](AgentRegistry::AgentEntry* agent_entry) { + agent_entry->AddDisconnectClosure( + &kRequestBufferUsageClosureName, + base::BindOnce(&Coordinator::OnRequestBufferStatusResponse, + base::Unretained(this), base::Unretained(agent_entry), + 0 /* capacity */, 0 /* count */)); + agent_entry->agent()->RequestBufferStatus(base::BindRepeating( + &Coordinator::OnRequestBufferStatusResponse, base::Unretained(this), + base::Unretained(agent_entry))); + }); +} + +void Coordinator::OnRequestBufferStatusResponse( + AgentRegistry::AgentEntry* agent_entry, + uint32_t capacity, + uint32_t count) { + bool removed = + agent_entry->RemoveDisconnectClosure(&kRequestBufferUsageClosureName); + DCHECK(removed); + + if (capacity > 0) { + float percent_full = + static_cast<float>(static_cast<double>(count) / capacity); + maximum_trace_buffer_usage_ = + std::max(maximum_trace_buffer_usage_, percent_full); + approximate_event_count_ += count; + } + + if (!agent_registry_->HasDisconnectClosure(&kRequestBufferUsageClosureName)) { + base::ResetAndReturn(&request_buffer_usage_callback_) + .Run(true, maximum_trace_buffer_usage_, approximate_event_count_); + } +} + +void Coordinator::GetCategories(const GetCategoriesCallback& callback) { + if (is_tracing_) { + callback.Run(false, ""); + } + + DCHECK(get_categories_callback_.is_null()); + is_tracing_ = true; + category_set_.clear(); + get_categories_callback_ = callback; + agent_registry_->ForAllAgents([this](AgentRegistry::AgentEntry* agent_entry) { + agent_entry->AddDisconnectClosure( + &kGetCategoriesClosureName, + base::BindOnce(&Coordinator::OnGetCategoriesResponse, + base::Unretained(this), base::Unretained(agent_entry), + "")); + agent_entry->agent()->GetCategories(base::BindRepeating( + &Coordinator::OnGetCategoriesResponse, base::Unretained(this), + base::Unretained(agent_entry))); + }); +} + +void Coordinator::OnGetCategoriesResponse( + AgentRegistry::AgentEntry* agent_entry, + const std::string& categories) { + bool removed = + agent_entry->RemoveDisconnectClosure(&kGetCategoriesClosureName); + DCHECK(removed); + + std::vector<std::string> split = base::SplitString( + categories, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + for (const auto& category : split) { + category_set_.insert(category); + } + + if (!agent_registry_->HasDisconnectClosure(&kGetCategoriesClosureName)) { + std::vector<std::string> category_vector(category_set_.begin(), + category_set_.end()); + base::ResetAndReturn(&get_categories_callback_) + .Run(true, base::JoinString(category_vector, ",")); + is_tracing_ = false; + } +} + +} // namespace tracing
diff --git a/services/resource_coordinator/tracing/coordinator.h b/services/resource_coordinator/tracing/coordinator.h new file mode 100644 index 0000000..758e79d --- /dev/null +++ b/services/resource_coordinator/tracing/coordinator.h
@@ -0,0 +1,103 @@ +// 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 SERVICES_RESOURCE_COORDINATOR_TRACING_COORDINATOR_H_ +#define SERVICES_RESOURCE_COORDINATOR_TRACING_COORDINATOR_H_ + +#include <map> +#include <memory> +#include <set> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" +#include "base/single_thread_task_runner.h" +#include "mojo/public/cpp/system/data_pipe.h" +#include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h" +#include "services/resource_coordinator/tracing/agent_registry.h" +#include "services/resource_coordinator/tracing/recorder.h" +#include "services/service_manager/public/cpp/bind_source_info.h" + +namespace tracing { + +// Note that this implementation of mojom::Coordinator assumes that agents +// either respond to messages that expect a response or disconnect. Mojo +// verifies this to some extend by DCHECKing if the callback is deleted by the +// agent before being run. However, the agent should not store the callback and +// never run it. +// +// If we see that the above-mentioned assumption does not hold in some cases, we +// should guard against it using timeouts. +class Coordinator : public mojom::Coordinator { + public: + static Coordinator* GetInstance(); + + Coordinator(); + + void BindCoordinatorRequest( + const service_manager::BindSourceInfo& source_info, + mojom::CoordinatorRequest request); + + private: + friend std::default_delete<Coordinator>; + friend class CoordinatorTest; // For testing. + + ~Coordinator() override; + + // mojom::Coordinator + void StartTracing(const std::string& config, + const StartTracingCallback& callback) override; + void StopAndFlush(mojo::ScopedDataPipeProducerHandle stream) override; + void IsTracing(const IsTracingCallback& callback) override; + void RequestBufferUsage(const RequestBufferUsageCallback& callback) override; + void GetCategories(const GetCategoriesCallback& callback) override; + + // Internal methods for collecting events from agents. + void SendStartTracingToAgent(AgentRegistry::AgentEntry* agent_entry); + void OnTracingStarted(AgentRegistry::AgentEntry* agent_entry); + void StopAndFlushInternal(); + void OnRecorderDataChange(const std::string& label); + bool StreamEventsForCurrentLabel(); + void StreamMetadata(); + void OnFlushDone(); + + void OnRequestBufferStatusResponse(AgentRegistry::AgentEntry* agent_entry, + uint32_t capacity, + uint32_t count); + + void OnGetCategoriesResponse(AgentRegistry::AgentEntry* agent_entry, + const std::string& categories); + + mojo::Binding<mojom::Coordinator> binding_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> background_task_runner_; + AgentRegistry* agent_registry_; + std::string config_; + std::map<std::string, std::set<std::unique_ptr<Recorder>>> recorders_; + bool is_tracing_ = false; + + // The stream to which trace events from different agents should be + // serialized, eventually. This is set when tracing is stopped. + mojo::ScopedDataPipeProducerHandle stream_; + // If |streaming_label_| is not empty, it shows the label for which we are + // writing chunks to the output stream. + std::string streaming_label_; + bool stream_header_written_ = false; + bool json_field_name_written_ = false; + StartTracingCallback start_tracing_callback_; + + // For computing trace buffer usage. + float maximum_trace_buffer_usage_ = 0; + uint32_t approximate_event_count_ = 0; + RequestBufferUsageCallback request_buffer_usage_callback_; + + // For getting categories. + std::set<std::string> category_set_; + GetCategoriesCallback get_categories_callback_; + + DISALLOW_COPY_AND_ASSIGN(Coordinator); +}; + +} // namespace tracing +#endif // SERVICES_RESOURCE_COORDINATOR_TRACING_COORDINATOR_H_
diff --git a/services/resource_coordinator/tracing/coordinator_unittest.cc b/services/resource_coordinator/tracing/coordinator_unittest.cc new file mode 100644 index 0000000..cf53430 --- /dev/null +++ b/services/resource_coordinator/tracing/coordinator_unittest.cc
@@ -0,0 +1,374 @@ +// 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 "services/resource_coordinator/tracing/coordinator.h" + +#include <algorithm> +#include <memory> +#include <set> +#include <string> +#include <utility> +#include <vector> + +#include "base/strings/string_split.h" +#include "base/test/scoped_task_environment.h" +#include "mojo/common/data_pipe_drainer.h" +#include "mojo/public/cpp/system/data_pipe.h" +#include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h" +#include "services/resource_coordinator/tracing/test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace tracing { + +class CoordinatorTest : public testing::Test, + public mojo::common::DataPipeDrainer::Client { + public: + // testing::Test + void SetUp() override { + agent_registry_.reset(new AgentRegistry()); + coordinator_.reset(new Coordinator()); + output_ = ""; + } + + // testing::Test + void TearDown() override { + agents_.clear(); + coordinator_.reset(); + agent_registry_.reset(); + } + + // mojo::common::DataPipeDrainer::Client + void OnDataAvailable(const void* data, size_t num_bytes) override { + output_.append(static_cast<const char*>(data), num_bytes); + } + + // mojo::common::DataPipeDrainer::Client + void OnDataComplete() override { base::ResetAndReturn(&quit_closure_).Run(); } + + MockAgent* AddArrayAgent() { + auto agent = base::MakeUnique<MockAgent>(); + agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "traceEvents", + mojom::TraceDataType::ARRAY, false); + agents_.push_back(std::move(agent)); + return agents_.back().get(); + } + + MockAgent* AddStringAgent() { + auto agent = base::MakeUnique<MockAgent>(); + agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "battor", + mojom::TraceDataType::STRING, false); + agents_.push_back(std::move(agent)); + return agents_.back().get(); + } + + void StartTracing(std::string config, + bool expected_response, + bool stop_and_flush) { + base::RepeatingClosure closure; + if (stop_and_flush) { + closure = base::BindRepeating(&CoordinatorTest::StopAndFlush, + base::Unretained(this)); + } + + coordinator_->StartTracing( + config, + base::BindRepeating( + [](bool expected, base::RepeatingClosure closure, bool actual) { + EXPECT_EQ(expected, actual); + if (!closure.is_null()) + closure.Run(); + }, + expected_response, closure)); + } + + void StartTracing(std::string config, bool expected_response) { + StartTracing(config, expected_response, false); + } + + void StopAndFlush() { + mojo::DataPipe data_pipe; + coordinator_->StopAndFlush(std::move(data_pipe.producer_handle)); + drainer_.reset(new mojo::common::DataPipeDrainer( + this, std::move(data_pipe.consumer_handle))); + } + + void IsTracing(bool expected_response) { + coordinator_->IsTracing(base::BindRepeating( + [](bool expected, bool actual) { EXPECT_EQ(expected, actual); }, + expected_response)); + } + + void RequestBufferUsage(float expected_usage, uint32_t expected_count) { + coordinator_->RequestBufferUsage(base::BindRepeating( + [](float expected_usage, uint32_t expected_count, bool success, + float usage, uint32_t count) { + EXPECT_TRUE(success); + EXPECT_EQ(expected_usage, usage); + EXPECT_EQ(expected_count, count); + }, + expected_usage, expected_count)); + } + + void CheckDisconnectClosures(size_t num_agents) { + // Verify that all disconnect closures are cleared up. This means that, for + // each agent, either the tracing service is notified that the agent is + // disconnected or the agent has answered to all requests. + size_t count = 0; + agent_registry_->ForAllAgents([&count](AgentRegistry::AgentEntry* entry) { + count++; + EXPECT_EQ(0u, entry->num_disconnect_closures_for_testing()); + }); + EXPECT_EQ(num_agents, count); + } + + void GetCategories(bool expected_success, + std::set<std::string> expected_categories) { + coordinator_->GetCategories(base::BindRepeating( + [](bool expected_success, std::set<std::string> expected_categories, + bool success, const std::string& categories) { + EXPECT_EQ(expected_success, success); + if (!success) + return; + std::vector<std::string> category_vector = base::SplitString( + categories, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + EXPECT_EQ(expected_categories.size(), category_vector.size()); + for (const auto& expected_category : expected_categories) { + EXPECT_EQ(1, std::count(category_vector.begin(), + category_vector.end(), expected_category)); + } + }, + expected_success, expected_categories)); + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<AgentRegistry> agent_registry_; + std::unique_ptr<Coordinator> coordinator_; + std::vector<std::unique_ptr<MockAgent>> agents_; + std::unique_ptr<mojo::common::DataPipeDrainer> drainer_; + base::RepeatingClosure quit_closure_; + std::string output_; +}; + +TEST_F(CoordinatorTest, StartTracingSimple) { + base::RunLoop run_loop; + auto* agent = AddArrayAgent(); + StartTracing("*", true); + run_loop.RunUntilIdle(); + + // The agent should have received exactly one call from the coordinator. + EXPECT_EQ(1u, agent->call_stat().size()); + EXPECT_EQ("StartTracing", agent->call_stat()[0]); +} + +TEST_F(CoordinatorTest, StartTracingTwoAgents) { + base::RunLoop run_loop; + auto* agent1 = AddArrayAgent(); + StartTracing("*", true); + auto* agent2 = AddStringAgent(); + run_loop.RunUntilIdle(); + + // Each agent should have received exactly one call from the coordinatr. + EXPECT_EQ(1u, agent1->call_stat().size()); + EXPECT_EQ("StartTracing", agent1->call_stat()[0]); + EXPECT_EQ(1u, agent2->call_stat().size()); + EXPECT_EQ("StartTracing", agent2->call_stat()[0]); +} + +TEST_F(CoordinatorTest, StartTracingWithDifferentConfigs) { + base::RunLoop run_loop; + auto* agent = AddArrayAgent(); + StartTracing("config 1", true); + // The 2nd |StartTracing| should return false. + StartTracing("config 2", false); + run_loop.RunUntilIdle(); + + // The agent should have received exactly one call from the coordinator + // because the 2nd |StartTracing| was aborted. + EXPECT_EQ(1u, agent->call_stat().size()); + EXPECT_EQ("StartTracing", agent->call_stat()[0]); +} + +TEST_F(CoordinatorTest, StartTracingWithSameConfigs) { + base::RunLoop run_loop; + auto* agent = AddArrayAgent(); + StartTracing("config", true); + // The 2nd |StartTracing| should return true when we are not trying to change + // the config. + StartTracing("config", true); + run_loop.RunUntilIdle(); + + // The agent should have received exactly one call from the coordinator + // because the 2nd |StartTracing| was a no-op. + EXPECT_EQ(1u, agent->call_stat().size()); + EXPECT_EQ("StartTracing", agent->call_stat()[0]); +} + +TEST_F(CoordinatorTest, StopAndFlushTwoArrayAgents) { + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + + auto* agent1 = AddArrayAgent(); + agent1->data_.push_back("e1"); + agent1->data_.push_back("e2"); + + auto* agent2 = AddArrayAgent(); + agent2->data_.push_back("e3"); + agent2->data_.push_back("e4"); + + StartTracing("config", true, true); + if (!quit_closure_.is_null()) + run_loop.Run(); + + // |output_| should be of the form {"traceEvents":[ei,ej,ek,el]}, where + // ei,ej,ek,el is a permutation of e1,e2,e3,e4 such that e1 is before e2 and + // e3 is before e4 since e1 and 2 come from the same agent and their order + // should be preserved and, similarly, the order of e3 and e4 should be + // preserved, too. + EXPECT_TRUE(output_ == "{\"traceEvents\":[e1,e2,e3,e4]}" || + output_ == "{\"traceEvents\":[e1,e3,e2,e4]}" || + output_ == "{\"traceEvents\":[e1,e3,e4,e2]}" || + output_ == "{\"traceEvents\":[e3,e1,e2,e4]}" || + output_ == "{\"traceEvents\":[e3,e1,e4,e2]}" || + output_ == "{\"traceEvents\":[e3,e4,e1,e2]}"); + + // Each agent should have received exactly two calls. + EXPECT_EQ(2u, agent1->call_stat().size()); + EXPECT_EQ("StartTracing", agent1->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent1->call_stat()[1]); + + EXPECT_EQ(2u, agent2->call_stat().size()); + EXPECT_EQ("StartTracing", agent2->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent2->call_stat()[1]); +} + +TEST_F(CoordinatorTest, StopAndFlushDifferentTypeAgents) { + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + + auto* agent1 = AddArrayAgent(); + agent1->data_.push_back("e1"); + agent1->data_.push_back("e2"); + + auto* agent2 = AddStringAgent(); + agent2->data_.push_back("e3"); + agent2->data_.push_back("e4"); + + StartTracing("config", true, true); + if (!quit_closure_.is_null()) + run_loop.Run(); + + EXPECT_TRUE(output_ == "{\"traceEvents\":[e1,e2],\"battor\":\"e3e4\"}" || + output_ == "{\"battor\":\"e3e4\",\"traceEvents\":[e1,e2]}"); + + // Each agent should have received exactly two calls. + EXPECT_EQ(2u, agent1->call_stat().size()); + EXPECT_EQ("StartTracing", agent1->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent1->call_stat()[1]); + + EXPECT_EQ(2u, agent2->call_stat().size()); + EXPECT_EQ("StartTracing", agent2->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent2->call_stat()[1]); +} + +TEST_F(CoordinatorTest, StopAndFlushWithMetadata) { + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + + auto* agent = AddArrayAgent(); + agent->data_.push_back("event"); + agent->metadata_.SetString("key", "value"); + + StartTracing("config", true, true); + if (!quit_closure_.is_null()) + run_loop.Run(); + + // Metadata is written at after trace data. + EXPECT_EQ("{\"traceEvents\":[event],\"metadata\":{\"key\":\"value\"}}", + output_); + EXPECT_EQ(2u, agent->call_stat().size()); + EXPECT_EQ("StartTracing", agent->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent->call_stat()[1]); +} + +TEST_F(CoordinatorTest, IsTracing) { + base::RunLoop run_loop; + StartTracing("config", true); + IsTracing(true); + run_loop.RunUntilIdle(); +} + +TEST_F(CoordinatorTest, IsNotTracing) { + base::RunLoop run_loop; + IsTracing(false); + run_loop.RunUntilIdle(); +} + +TEST_F(CoordinatorTest, RequestBufferUsage) { + auto* agent1 = AddArrayAgent(); + agent1->trace_log_status_.event_capacity = 4; + agent1->trace_log_status_.event_count = 1; + RequestBufferUsage(0.25, 1); + base::RunLoop().RunUntilIdle(); + CheckDisconnectClosures(1); + + auto* agent2 = AddArrayAgent(); + agent2->trace_log_status_.event_capacity = 8; + agent2->trace_log_status_.event_count = 1; + // The buffer usage of |agent2| is less than the buffer usage of |agent1| and + // so the total buffer usage, i.e 0.25, does not change. But, the approximage + // count will be increased from 1 to 2. + RequestBufferUsage(0.25, 2); + base::RunLoop().RunUntilIdle(); + CheckDisconnectClosures(2); + + base::RunLoop run_loop3; + auto* agent3 = AddArrayAgent(); + agent3->trace_log_status_.event_capacity = 8; + agent3->trace_log_status_.event_count = 4; + // |agent3| has the worst buffer usage of 0.5. + RequestBufferUsage(0.5, 6); + base::RunLoop().RunUntilIdle(); + CheckDisconnectClosures(3); + + // At the end |agent1| receveis 3 calls, |agent2| receives 2 calls, and + // |agent3| receives 1 call. + EXPECT_EQ(3u, agent1->call_stat().size()); + EXPECT_EQ(2u, agent2->call_stat().size()); + EXPECT_EQ(1u, agent3->call_stat().size()); +} + +TEST_F(CoordinatorTest, GetCategoriesFail) { + base::RunLoop run_loop; + StartTracing("config", true); + std::set<std::string> expected_categories; + GetCategories(false, expected_categories); + run_loop.RunUntilIdle(); +} + +TEST_F(CoordinatorTest, GetCategoriesSimple) { + base::RunLoop run_loop; + auto* agent = AddArrayAgent(); + agent->categories_ = "cat2,cat1"; + std::set<std::string> expected_categories; + expected_categories.insert("cat1"); + expected_categories.insert("cat2"); + GetCategories(true, expected_categories); + run_loop.RunUntilIdle(); +} + +TEST_F(CoordinatorTest, GetCategoriesFromTwoAgents) { + base::RunLoop run_loop; + auto* agent1 = AddArrayAgent(); + agent1->categories_ = "cat2,cat1"; + auto* agent2 = AddArrayAgent(); + agent2->categories_ = "cat3,cat2"; + std::set<std::string> expected_categories; + expected_categories.insert("cat1"); + expected_categories.insert("cat2"); + expected_categories.insert("cat3"); + GetCategories(true, expected_categories); + run_loop.RunUntilIdle(); +} + +} // namespace tracing
diff --git a/services/resource_coordinator/tracing/recorder.cc b/services/resource_coordinator/tracing/recorder.cc index 7997cb1..2701449 100644 --- a/services/resource_coordinator/tracing/recorder.cc +++ b/services/resource_coordinator/tracing/recorder.cc
@@ -20,10 +20,29 @@ data_is_array_(data_is_array), on_data_change_callback_(on_data_change_callback), background_task_runner_(background_task_runner), - binding_(this, std::move(request)), - weak_factory_(this) { + binding_(this, std::move(request)) { + // A recorder should be deleted only if |is_recording_| is false to ensure + // that: + // + // 1- |OnConnectionError| is already executed and so using Unretained(this) is + // safe here. + // + // 2- The task possibly posted by |OnConnectionError| is already executed and + // so using Unretained(this) is safe in that PostTask. + // + // 3- Since the connection is closed, the tasks posted by |AddChunk| are + // already executed and so using Unretained(this) is safe in the PostTask in + // |AddChunk|. + // + // We cannot use a weak pointer factory here since the weak pointers should be + // dereferenced on the same SequencedTaskRunner. We could use two weak pointer + // factories but that increases the complexity of the code since each factory + // should be created on the correct thread and we should deal with cases that + // one of the factories is not created, yet. + // + // The tracing coordinator deletes a recorder when |is_recording_| is false. binding_.set_connection_error_handler(base::BindRepeating( - &Recorder::OnConnectionError, weak_factory_.GetWeakPtr())); + &Recorder::OnConnectionError, base::Unretained(this))); } Recorder::~Recorder() = default; @@ -34,7 +53,7 @@ if (!background_task_runner_->RunsTasksInCurrentSequence()) { background_task_runner_->PostTask( FROM_HERE, base::BindRepeating(&Recorder::AddChunk, - weak_factory_.GetWeakPtr(), chunk)); + base::Unretained(this), chunk)); return; } if (data_is_array_ && !data_.empty()) @@ -48,8 +67,14 @@ } void Recorder::OnConnectionError() { + if (!background_task_runner_->RunsTasksOnCurrentThread()) { + background_task_runner_->PostTask( + FROM_HERE, base::BindRepeating(&Recorder::OnConnectionError, + base::Unretained(this))); + return; + } is_recording_ = false; - background_task_runner_->PostTask(FROM_HERE, on_data_change_callback_); + on_data_change_callback_.Run(); } } // namespace tracing
diff --git a/services/resource_coordinator/tracing/recorder.h b/services/resource_coordinator/tracing/recorder.h index 1530c6c..78fee95e7 100644 --- a/services/resource_coordinator/tracing/recorder.h +++ b/services/resource_coordinator/tracing/recorder.h
@@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/values.h" #include "mojo/public/cpp/bindings/binding.h" @@ -76,7 +75,6 @@ // final stream is done on a background thread. scoped_refptr<base::SequencedTaskRunner> background_task_runner_; mojo::Binding<mojom::Recorder> binding_; - base::WeakPtrFactory<Recorder> weak_factory_; DISALLOW_COPY_AND_ASSIGN(Recorder); };
diff --git a/services/resource_coordinator/tracing/test_util.cc b/services/resource_coordinator/tracing/test_util.cc new file mode 100644 index 0000000..28ffbb3 --- /dev/null +++ b/services/resource_coordinator/tracing/test_util.cc
@@ -0,0 +1,55 @@ +// 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 "services/resource_coordinator/tracing/test_util.h" + +#include <string> + +#include "base/memory/ptr_util.h" +#include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h" + +namespace tracing { + +MockAgent::MockAgent() : binding_(this) {} + +MockAgent::~MockAgent() = default; + +mojom::AgentPtr MockAgent::CreateAgentPtr() { + mojom::AgentPtr agent_proxy; + binding_.Bind(mojo::MakeRequest(&agent_proxy)); + return agent_proxy; +} + +void MockAgent::StartTracing(const std::string& config, + const StartTracingCallback& cb) { + call_stat_.push_back("StartTracing"); + cb.Run(); +} + +void MockAgent::StopAndFlush(mojom::RecorderPtr recorder) { + call_stat_.push_back("StopAndFlush"); + if (!metadata_.empty()) + recorder->AddMetadata(base::MakeUnique<base::DictionaryValue>(metadata_)); + for (const auto& chunk : data_) { + recorder->AddChunk(chunk); + } +} + +void MockAgent::RequestClockSyncMarker( + const std::string& sync_id, + const RequestClockSyncMarkerCallback& cb) { + call_stat_.push_back("RequestClockSyncMarker"); +} + +void MockAgent::GetCategories(const GetCategoriesCallback& cb) { + call_stat_.push_back("GetCategories"); + cb.Run(categories_); +} + +void MockAgent::RequestBufferStatus(const RequestBufferStatusCallback& cb) { + call_stat_.push_back("RequestBufferStatus"); + cb.Run(trace_log_status_.event_capacity, trace_log_status_.event_count); +} + +} // namespace tracing
diff --git a/services/resource_coordinator/tracing/test_util.h b/services/resource_coordinator/tracing/test_util.h new file mode 100644 index 0000000..9f92afd0 --- /dev/null +++ b/services/resource_coordinator/tracing/test_util.h
@@ -0,0 +1,50 @@ +// 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 SERVICES_RESOURCE_COORDINATOR_TRACING_TEST_UTIL_H_ +#define SERVICES_RESOURCE_COORDINATOR_TRACING_TEST_UTIL_H_ + +#include <string> +#include <vector> + +#include "base/trace_event/trace_log.h" +#include "base/values.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h" + +namespace tracing { + +class MockAgent : public mojom::Agent { + public: + MockAgent(); + ~MockAgent() override; + + mojom::AgentPtr CreateAgentPtr(); + + std::vector<std::string> call_stat() const { return call_stat_; } + + // Set these variables to configure the agent. + std::vector<std::string> data_; + base::DictionaryValue metadata_; + std::string categories_; + base::trace_event::TraceLogStatus trace_log_status_; + + private: + // mojom::Agent + void StartTracing(const std::string& config, + const StartTracingCallback& cb) override; + void StopAndFlush(mojom::RecorderPtr recorder) override; + void RequestClockSyncMarker( + const std::string& sync_id, + const RequestClockSyncMarkerCallback& cb) override; + void GetCategories(const GetCategoriesCallback& cb) override; + void RequestBufferStatus(const RequestBufferStatusCallback& cb) override; + + mojo::Binding<mojom::Agent> binding_; + std::vector<std::string> call_stat_; +}; + +} // namespace tracing + +#endif // SERVICES_RESOURCE_COORDINATOR_TRACING_TEST_UTIL_H_
diff --git a/services/shape_detection/barcode_detection_impl_mac.h b/services/shape_detection/barcode_detection_impl_mac.h index 6a5609a..062a68b 100644 --- a/services/shape_detection/barcode_detection_impl_mac.h +++ b/services/shape_detection/barcode_detection_impl_mac.h
@@ -20,8 +20,8 @@ ~BarcodeDetectionImplMac() override; void Detect(const SkBitmap& bitmap, - const shape_detection::mojom::BarcodeDetection::DetectCallback& - callback) override; + shape_detection::mojom::BarcodeDetection::DetectCallback callback) + override; private: base::scoped_nsobject<CIDetector> detector_;
diff --git a/services/shape_detection/barcode_detection_impl_mac.mm b/services/shape_detection/barcode_detection_impl_mac.mm index 23569cd..a3df01e2 100644 --- a/services/shape_detection/barcode_detection_impl_mac.mm +++ b/services/shape_detection/barcode_detection_impl_mac.mm
@@ -17,16 +17,9 @@ namespace { -void RunCallbackWithBarcodes( - const shape_detection::mojom::BarcodeDetection::DetectCallback& callback, - std::vector<shape_detection::mojom::BarcodeDetectionResultPtr> results) { - callback.Run(std::move(results)); -} - void RunCallbackWithNoBarcodes( shape_detection::mojom::BarcodeDetection::DetectCallback callback) { - callback.Run( - std::vector<shape_detection::mojom::BarcodeDetectionResultPtr>()); + std::move(callback).Run({}); } } // anonymous namespace @@ -52,10 +45,9 @@ BarcodeDetectionImplMac::~BarcodeDetectionImplMac() {} void BarcodeDetectionImplMac::Detect(const SkBitmap& bitmap, - const DetectCallback& callback) { + DetectCallback callback) { media::ScopedResultCallback<DetectCallback> scoped_callback( - base::Bind(&RunCallbackWithBarcodes, callback), - base::Bind(&RunCallbackWithNoBarcodes)); + std::move(callback), base::Bind(&RunCallbackWithNoBarcodes)); base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); if (!ci_image)
diff --git a/services/shape_detection/face_detection_impl_mac.h b/services/shape_detection/face_detection_impl_mac.h index 459ffa7..51d6ac2 100644 --- a/services/shape_detection/face_detection_impl_mac.h +++ b/services/shape_detection/face_detection_impl_mac.h
@@ -19,9 +19,9 @@ shape_detection::mojom::FaceDetectorOptionsPtr options); ~FaceDetectionImplMac() override; - void Detect(const SkBitmap& bitmap, - const shape_detection::mojom::FaceDetection::DetectCallback& - callback) override; + void Detect( + const SkBitmap& bitmap, + shape_detection::mojom::FaceDetection::DetectCallback callback) override; private: base::scoped_nsobject<CIDetector> detector_;
diff --git a/services/shape_detection/face_detection_impl_mac.mm b/services/shape_detection/face_detection_impl_mac.mm index d7547e0..29648c3 100644 --- a/services/shape_detection/face_detection_impl_mac.mm +++ b/services/shape_detection/face_detection_impl_mac.mm
@@ -14,15 +14,9 @@ namespace { -void RunCallbackWithFaces( - const shape_detection::mojom::FaceDetection::DetectCallback& callback, - std::vector<shape_detection::mojom::FaceDetectionResultPtr> results) { - callback.Run(std::move(results)); -} - void RunCallbackWithNoFaces( shape_detection::mojom::FaceDetection::DetectCallback callback) { - callback.Run(std::vector<shape_detection::mojom::FaceDetectionResultPtr>()); + std::move(callback).Run({}); } } // anonymous namespace @@ -48,10 +42,9 @@ FaceDetectionImplMac::~FaceDetectionImplMac() {} void FaceDetectionImplMac::Detect(const SkBitmap& bitmap, - const DetectCallback& callback) { + DetectCallback callback) { media::ScopedResultCallback<DetectCallback> scoped_callback( - base::Bind(&RunCallbackWithFaces, callback), - base::Bind(&RunCallbackWithNoFaces)); + std::move(callback), base::Bind(&RunCallbackWithNoFaces)); base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); if (!ci_image)
diff --git a/services/shape_detection/public/interfaces/BUILD.gn b/services/shape_detection/public/interfaces/BUILD.gn index 432da86..44522415 100644 --- a/services/shape_detection/public/interfaces/BUILD.gn +++ b/services/shape_detection/public/interfaces/BUILD.gn
@@ -17,10 +17,4 @@ "//skia/public/interfaces", "//ui/gfx/geometry/mojo", ] - - # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. - use_once_callback = false - - # TODO(crbug.com/699569): Convert to use the new JS bindings. - use_new_js_bindings = false }
diff --git a/services/shape_detection/text_detection_impl_mac.h b/services/shape_detection/text_detection_impl_mac.h index 738d8da..64563c67 100644 --- a/services/shape_detection/text_detection_impl_mac.h +++ b/services/shape_detection/text_detection_impl_mac.h
@@ -18,7 +18,7 @@ ~TextDetectionImplMac() override; void Detect(const SkBitmap& bitmap, - const mojom::TextDetection::DetectCallback& callback) override; + mojom::TextDetection::DetectCallback callback) override; private: base::scoped_nsobject<CIDetector> detector_;
diff --git a/services/shape_detection/text_detection_impl_mac.mm b/services/shape_detection/text_detection_impl_mac.mm index 779c341..f645cce 100644 --- a/services/shape_detection/text_detection_impl_mac.mm +++ b/services/shape_detection/text_detection_impl_mac.mm
@@ -17,14 +17,8 @@ namespace { -void RunCallbackWithResults( - const mojom::TextDetection::DetectCallback& callback, - std::vector<mojom::TextDetectionResultPtr> results) { - callback.Run(std::move(results)); -} - void RunCallbackWithNoResults(mojom::TextDetection::DetectCallback callback) { - callback.Run(std::vector<mojom::TextDetectionResultPtr>()); + std::move(callback).Run({}); } } // anonymous namespace @@ -50,11 +44,10 @@ TextDetectionImplMac::~TextDetectionImplMac() {} void TextDetectionImplMac::Detect(const SkBitmap& bitmap, - const DetectCallback& callback) { + DetectCallback callback) { DCHECK(base::mac::IsAtLeastOS10_11()); media::ScopedResultCallback<DetectCallback> scoped_callback( - base::Bind(&RunCallbackWithResults, callback), - base::Bind(&RunCallbackWithNoResults)); + std::move(callback), base::Bind(&RunCallbackWithNoResults)); base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); if (!ci_image)
diff --git a/skia/public/interfaces/BUILD.gn b/skia/public/interfaces/BUILD.gn index 5dc61b7..3b935a2 100644 --- a/skia/public/interfaces/BUILD.gn +++ b/skia/public/interfaces/BUILD.gn
@@ -9,9 +9,6 @@ "bitmap.mojom", "image_filter.mojom", ] - - # TODO(crbug.com/699569): Convert to use the new JS bindings. - use_new_js_bindings = false } mojom("test_interfaces") {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 9bd8bab..df6a60f 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -290,6 +290,44 @@ "test": "chrome_public_test_vr_apk" }, { + "args": [ + "--shared-prefs-file=../../chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json", + "--replace-system-package=com.google.vr.vrcore,../../third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk" + ], + "name": "chrome_public_test_vr_apk-marlin-cardboard-nougat", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_os": "NMF26U", + "device_type": "marlin" + } + ], + "hard_timeout": 960 + }, + "test": "chrome_public_test_vr_apk" + }, + { + "args": [ + "--shared-prefs-file=../../chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json", + "--replace-system-package=com.google.vr.vrcore,../../third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk" + ], + "name": "chrome_public_test_vr_apk-marlin-ddview-nougat", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_os": "NMF26U", + "device_type": "marlin" + } + ], + "hard_timeout": 960 + }, + "test": "chrome_public_test_vr_apk" + }, + { "swarming": { "can_use_on_swarming_builders": false },
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 563e05f..35f89e28 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -10740,6 +10740,22 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Ubuntu" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -10911,6 +10927,22 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -11037,6 +11069,23 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -11165,6 +11214,22 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -11291,6 +11356,23 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -11421,6 +11503,23 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "Mac" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -11551,6 +11650,23 @@ } ] }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0fe9", + "hidpi": "1", + "os": "Mac" + } + ] + }, "test": "gles2_conform_test", "use_xvfb": false }, @@ -11703,6 +11819,22 @@ }, { "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6613", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests", "--use-angle=d3d9" ], @@ -11946,6 +12078,22 @@ }, { "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests", "--use-angle=d3d9" ],
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index bbcb21ac..9c17388d 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -3810,6 +3810,65 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build249-m4--device1", + "os": "Android", + "pool": "Chrome-perf-fyi" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build249-m4--device1", + "os": "Android", + "pool": "Chrome-perf-fyi" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -4754,6 +4813,31 @@ } ] }, + "Mojo Linux Perf": { + "isolated_scripts": [ + { + "args": [ + "loading.desktop.network_service", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=release" + ], + "isolate_name": "telemetry_perf_tests", + "name": "loading.desktop.network_service", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + } + ] + }, "Win 10 4 Core Low-End Perf Tests": { "isolated_scripts": [ {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 37055978..0949bf09 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -3855,6 +3855,65 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build48-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build48-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -8648,6 +8707,65 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build75-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build75-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -11566,6 +11684,36 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-webview", + "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" + ], + "isolate_name": "telemetry_perf_webview_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_webview_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build166-b1--device3", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -15895,6 +16043,65 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build45-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build45-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -18813,6 +19020,36 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-webview", + "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" + ], + "isolate_name": "telemetry_perf_webview_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_webview_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build114-b1--device3", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -23142,6 +23379,65 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build49-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build49-b1--device1", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results", @@ -27935,6 +28231,65 @@ }, { "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build18-b1--device7", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + }, + { + "args": [ + "tab_switching.typical_25", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=reference", + "--output-trace-tag=_ref" + ], + "isolate_name": "telemetry_perf_tests", + "name": "tab_switching.typical_25.reference", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "id": "build18-b1--device7", + "os": "Android", + "pool": "Chrome-perf" + } + ], + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": true, + "io_timeout": 3600 + } + }, + { + "args": [ "thread_times.key_hit_test_cases", "-v", "--upload-results",
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index 8285dec5..19fa3da 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -92,6 +92,7 @@ -PaymentAppBrowserTest.PaymentAppInvocation -PaymentAppBrowserTest.PaymentAppOpenWindowFailed -PlzNavigateNavigationHandleImplBrowserTest.ErrorPageNetworkError +-PowerMonitorTest.TestGpuProcess -PowerMonitorTest.TestRendererProcess -PowerMonitorTest.TestUtilityProcess -PreviewsStateResourceDispatcherHostBrowserTest.ShouldEnableLoFiModeNavigateBackThenForward
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index d0c0b6e..4fa3fca 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -462,12 +462,15 @@ ] } -# TODO(yawano): Add compress test case -fuzzer_test("minizip_uncompress_fuzzer") { - sources = [ - "minizip_uncompress_fuzzer.cc", - ] - deps = [ - "//third_party/minizip:minizip", - ] +# third_party/minizip/src is checked out only on unix platform by gclient. +if (is_linux) { + # TODO(yawano): Add compress test case + fuzzer_test("minizip_uncompress_fuzzer") { + sources = [ + "minizip_uncompress_fuzzer.cc", + ] + deps = [ + "//third_party/minizip:minizip", + ] + } }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 83c4156a..efa8894 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -147,13 +147,9 @@ ], "experiments": [ { - "name": "LastUsedDate_IncreaseDropdownItemHeight_Experiment", - "params": { - "dropdown_item_height": "56" - }, + "name": "BankName_Experiment", "enable_features": [ - "AutofillCreditCardLastUsedDateDisplay", - "AutofillCreditCardPopupLayout" + "AutofillCreditCardBankNameDisplay" ] } ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 339e5ac..928eb277 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -230,7 +230,6 @@ crbug.com/591099 animations/3d/state-at-end-event-transform.html [ Failure Pass ] crbug.com/591099 animations/animation-css-rule-types.html [ Failure ] crbug.com/591099 animations/animation-events-create.html [ Failure ] -crbug.com/591099 animations/prefixed/animation-inherit-initial-unprefixed.html [ Failure ] crbug.com/591099 animations/animations-parsing.html [ Timeout ] crbug.com/591099 animations/animations-responsive-to-color-change.html [ Crash ] crbug.com/591099 animations/clear-svg-animation-effects.html [ Crash ] @@ -329,13 +328,14 @@ crbug.com/591099 animations/interpolation/webkit-text-stroke-color-interpolation.html [ Crash ] crbug.com/591099 animations/interpolation/webkit-transform-interpolation.html [ Crash ] crbug.com/591099 animations/interpolation/webkit-transform-origin-interpolation.html [ Crash ] -crbug.com/591099 animations/prefixed/keyframes-cssom-prefixed-02.html [ Failure ] -crbug.com/591099 animations/prefixed/keyframes-cssom-unprefixed-02.html [ Failure ] crbug.com/591099 animations/keyframes-rule.html [ Failure ] crbug.com/591099 animations/lazy-detached-animation-stop.html [ Failure ] crbug.com/591099 animations/negative-delay-events.html [ Failure ] crbug.com/591099 animations/play-state-initially-paused-start-event.html [ Failure ] crbug.com/591099 animations/play-state.html [ Failure ] +crbug.com/591099 animations/prefixed/animation-inherit-initial-unprefixed.html [ Failure ] +crbug.com/591099 animations/prefixed/keyframes-cssom-prefixed-02.html [ Failure ] +crbug.com/591099 animations/prefixed/keyframes-cssom-unprefixed-02.html [ Failure ] crbug.com/591099 animations/responsive/d-responsive.html [ Crash ] crbug.com/591099 animations/responsive/line-height-responsive.html [ Pass Timeout ] crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] @@ -718,6 +718,7 @@ crbug.com/591099 compositing/overflow/clip-descendents.html [ Failure ] crbug.com/591099 compositing/overflow/clip-parent-reset.html [ Failure ] crbug.com/591099 compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html [ Failure ] +crbug.com/591099 compositing/overflow/composited-layer-under-border-radius-under-composited-layer.html [ Failure ] crbug.com/591099 compositing/overflow/composited-nested-sticky-left.html [ Failure ] crbug.com/591099 compositing/overflow/composited-scrolling-paint-phases.html [ Failure ] crbug.com/591099 compositing/overflow/content-gains-scrollbars.html [ Failure ] @@ -4105,7 +4106,7 @@ crbug.com/591099 external/wpt/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html [ Crash ] crbug.com/591099 external/wpt/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html [ Crash ] crbug.com/591099 external/wpt/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html [ Crash ] -crbug.com/591099 external/wpt/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.emptysrc.html [ Crash ] +crbug.com/591099 external/wpt/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.emptysrc.html [ Crash Pass ] crbug.com/591099 external/wpt/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.removedsrc.html [ Crash ] crbug.com/591099 external/wpt/2dcontext/hit-regions/hitregions-members-exist.html [ Crash ] crbug.com/591099 external/wpt/2dcontext/line-styles/setLineDash.html [ Crash ] @@ -4137,6 +4138,8 @@ crbug.com/591099 external/wpt/XMLHttpRequest/send-authentication-prompt-2-manual.htm [ Crash Failure ] crbug.com/591099 external/wpt/XMLHttpRequest/xmlhttprequest-sync-block-defer-scripts.html [ Crash ] crbug.com/591099 external/wpt/XMLHttpRequest/xmlhttprequest-sync-not-hang-scriptloader.html [ Crash ] +crbug.com/591099 external/wpt/clear-site-data/navigation-insecure.html [ Crash ] +crbug.com/591099 external/wpt/clear-site-data/navigation.https.html [ Crash ] crbug.com/591099 external/wpt/content-security-policy/child-src/child-src-about-blank-allowed-by-default.sub.html [ Crash ] crbug.com/591099 external/wpt/content-security-policy/child-src/child-src-about-blank-allowed-by-scheme.sub.html [ Crash ] crbug.com/591099 external/wpt/content-security-policy/child-src/child-src-allowed.sub.html [ Crash ] @@ -4183,6 +4186,39 @@ crbug.com/591099 external/wpt/content-security-policy/svg/svg-policy-resource-doc-includes.html [ Crash ] crbug.com/591099 external/wpt/content-security-policy/svg/svg-policy-with-resource.html [ Crash ] crbug.com/591099 external/wpt/cors/remote-origin.htm [ Crash ] +crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-001.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-002.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-003.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-tiled-001.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-tiled-002.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-tiled-003.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-001.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-002.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-003.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-004.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-005.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/paint2d-zoom.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-001.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-002.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-003.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-004.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-005.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-006.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-007.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-008.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-009.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-010.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-011.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-012.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-013.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-014.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-015.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-016.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-017.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/registered-properties-in-custom-paint.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/style-background-image.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/style-before-pseudo.html [ Failure Pass ] +crbug.com/591099 external/wpt/css-paint-api/style-first-letter-pseudo.html [ Failure Pass ] crbug.com/591099 external/wpt/css/CSS2/abspos/abspos-containing-block-initial-001.xht [ Failure ] crbug.com/591099 external/wpt/css/CSS2/abspos/abspos-containing-block-initial-009a.xht [ Failure ] crbug.com/591099 external/wpt/css/CSS2/floats-clear/float-replaced-width-002.xht [ Failure ] @@ -5223,39 +5259,6 @@ crbug.com/591099 external/wpt/cssom-view/scrollingElement.html [ Crash ] crbug.com/591099 external/wpt/cssom-view/ttwf-js-cssomview-getclientrects-length.html [ Crash ] crbug.com/591099 external/wpt/cssom/serialize-values.html [ Pass Timeout ] -crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-tiled-001.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-tiled-002.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-tiled-003.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-001.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-002.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-background-image-003.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-001.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-002.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-003.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-004.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/geometry-border-image-005.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/paint2d-zoom.html [ Failure Pass ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-001.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-002.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-003.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-004.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-005.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-006.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-007.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-008.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-009.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-010.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-011.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-012.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-013.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-014.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-015.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-016.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/parse-input-arguments-017.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/registered-properties-in-custom-paint.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/style-background-image.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/style-before-pseudo.html [ Failure ] -crbug.com/591099 external/wpt/css-paint-api/style-first-letter-pseudo.html [ Failure ] crbug.com/591099 external/wpt/custom-elements/custom-element-reaction-queue.html [ Crash ] crbug.com/591099 external/wpt/custom-elements/custom-element-registry/per-global.html [ Crash ] crbug.com/591099 external/wpt/custom-elements/htmlconstructor/newtarget.html [ Crash ] @@ -5337,7 +5340,75 @@ crbug.com/591099 external/wpt/editing/run/superscript.html [ Pass Timeout ] crbug.com/591099 external/wpt/editing/run/underline.html [ Pass Timeout ] crbug.com/591099 external/wpt/encoding/api-invalid-label.html [ Pass Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-csshiftjis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-ms932.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-ms_kanji.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-shift-jis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-sjis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-windows-31j.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-x-sjis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-csshiftjis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-han.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-hangul.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-errors-misc.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-ms932.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-ms_kanji.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-shift-jis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-sjis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-windows-31j.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form-x-sjis.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-form.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-han.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-hangul.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-href-errors-misc.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-encode-href.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-cseuckr.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-csksc56011987.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-iso-ir-149.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-korean.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ks_c_5601-1987.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ks_c_5601-1989.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc5601.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc_5601.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-windows-949.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-cseuckr.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-csksc56011987.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-han.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-misc.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-iso-ir-149.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-korean.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-ks_c_5601-1987.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-ks_c_5601-1989.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-ksc5601.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-ksc_5601.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-windows-949.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-han.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-misc.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-href.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-big5-hkscs.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-cn-big5.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-csbig5.html [ Timeout ] crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-extra.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-x-x-big5.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-big5-hkscs.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-cn-big5.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-csbig5.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBa.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBb.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-han.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-hangul.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-misc.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-pua.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-x-x-big5.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-han.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-hangul.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-misc.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href.html [ Timeout ] crbug.com/591099 external/wpt/encoding/textdecoder-fatal-single-byte.html [ Timeout ] crbug.com/591099 external/wpt/eventsource/eventsource-onmessage-realm.htm [ Crash ] crbug.com/591099 external/wpt/fetch/api/request/multi-globals/url-parsing.html [ Crash ] @@ -10649,6 +10720,7 @@ crbug.com/591099 fast/forms/image-disconnected-during-parse.html [ Failure ] crbug.com/591099 fast/forms/image/002.html [ Crash Failure ] crbug.com/591099 fast/forms/image/005.html [ Failure ] +crbug.com/591099 fast/forms/image/fallback-reattach-crash.html [ Crash ] crbug.com/591099 fast/forms/image/image-error-event-modifies-type-crash.html [ Crash Failure ] crbug.com/591099 fast/forms/image/image-setrangetext.html [ Crash Failure ] crbug.com/591099 fast/forms/image/input-align-image.html [ Failure ] @@ -14625,7 +14697,7 @@ crbug.com/591099 http/tests/inspector-protocol/network-data-length.html [ Failure Timeout ] crbug.com/591099 http/tests/inspector-protocol/network-fetch-content-with-error-status-code.html [ Failure Timeout ] crbug.com/591099 http/tests/inspector-protocol/network/disable-interception-midway.html [ Failure Timeout ] -crbug.com/591099 http/tests/inspector-protocol/network/interception-auth-cancel.html [ Failure ] +crbug.com/591099 http/tests/inspector-protocol/network/interception-auth-cancel.html [ Failure Timeout ] crbug.com/591099 http/tests/inspector-protocol/network/interception-auth-provide-credentials.html [ Failure Timeout ] crbug.com/591099 http/tests/inspector-protocol/network/navigation-interception.html [ Failure ] crbug.com/591099 http/tests/inspector-protocol/network/redirect-interception-blocked.html [ Failure ] @@ -16651,7 +16723,7 @@ crbug.com/591099 inspector/elements/reveal-whitespace-text-node.html [ Crash ] crbug.com/591099 inspector/elements/selected-element-changes-execution-context.html [ Crash ] crbug.com/591099 inspector/elements/shadow/breadcrumb-shadow-roots.html [ Crash ] -crbug.com/591099 inspector/elements/shadow/create-shadow-root.html [ Crash ] +crbug.com/591099 inspector/elements/shadow/create-shadow-root.html [ Crash Timeout ] crbug.com/591099 inspector/elements/shadow/elements-panel-shadow-selection-on-refresh-1.html [ Crash ] crbug.com/591099 inspector/elements/shadow/elements-panel-shadow-selection-on-refresh-2.html [ Crash ] crbug.com/591099 inspector/elements/shadow/elements-panel-shadow-selection-on-refresh-3.html [ Crash ] @@ -16778,7 +16850,7 @@ crbug.com/591099 inspector/elements/styles/undo-after-cancelled-editing.html [ Crash ] crbug.com/591099 inspector/elements/styles/undo-change-property.html [ Crash ] crbug.com/591099 inspector/elements/styles/undo-property-toggle.html [ Crash ] -crbug.com/591099 inspector/elements/styles/undo-set-selector-text.html [ Crash ] +crbug.com/591099 inspector/elements/styles/undo-set-selector-text.html [ Crash Timeout ] crbug.com/591099 inspector/elements/styles/up-down-numerics-and-colors.html [ Crash ] crbug.com/591099 inspector/elements/styles/updates-during-dom-traversal.html [ Crash ] crbug.com/591099 inspector/elements/styles/updates-throttled.html [ Crash ] @@ -16791,7 +16863,7 @@ crbug.com/591099 inspector/file-system-project.html [ Failure ] crbug.com/591099 inspector/filtered-item-selection-dialog-rendering.html [ Failure ] crbug.com/591099 inspector/geolocation-emulation-tests.html [ Failure ] -crbug.com/591099 inspector/help/release-note-unit.html [ Failure ] +crbug.com/591099 inspector/help/release-note-unit.html [ Crash Failure ] crbug.com/591099 inspector/help/release-note.html [ Crash ] crbug.com/591099 inspector/import-open-inspector.html [ Failure ] crbug.com/591099 inspector/initial-modules-load.html [ Failure ] @@ -16934,7 +17006,7 @@ crbug.com/591099 inspector/sources/debugger-breakpoints/dynamic-scripts-breakpoints.html [ Crash Failure ] crbug.com/591099 inspector/sources/debugger-breakpoints/event-listener-breakpoints-after-suspension.html [ Failure ] crbug.com/591099 inspector/sources/debugger-breakpoints/event-listener-breakpoints-script-first-stmt.html [ Crash Failure ] -crbug.com/591099 inspector/sources/debugger-breakpoints/event-listener-breakpoints-xhr.html [ Failure ] +crbug.com/591099 inspector/sources/debugger-breakpoints/event-listener-breakpoints-xhr.html [ Crash Failure ] crbug.com/591099 inspector/sources/debugger-breakpoints/event-listener-breakpoints.html [ Failure ] crbug.com/591099 inspector/sources/debugger-breakpoints/nodejs-set-breakpoint.html [ Failure ] crbug.com/591099 inspector/sources/debugger-breakpoints/possible-breakpoints.html [ Crash Failure ] @@ -18629,7 +18701,7 @@ crbug.com/591099 storage/indexeddb/events.html [ Failure ] crbug.com/591099 storage/indexeddb/exception-in-event-aborts.html [ Failure ] crbug.com/591099 storage/indexeddb/exceptions.html [ Timeout ] -crbug.com/591099 storage/indexeddb/factory-cmp.html [ Timeout ] +crbug.com/591099 storage/indexeddb/factory-cmp.html [ Failure Timeout ] crbug.com/591099 storage/indexeddb/factory-deletedatabase.html [ Failure ] crbug.com/591099 storage/indexeddb/get-keyrange.html [ Failure ] crbug.com/591099 storage/indexeddb/index-basics-workers.html [ Failure ] @@ -20262,6 +20334,7 @@ crbug.com/591099 vibration/vibration-exceptions.html [ Failure ] crbug.com/591099 vibration/vibration-iframe.html [ Timeout ] crbug.com/591099 vibration/vibration-patterns.html [ Failure ] +crbug.com/591099 virtual/android/fast/rootscroller/set-root-scroller.html [ Failure ] crbug.com/591099 virtual/android/fullscreen/anonymous-block-merge-crash.html [ Crash ] crbug.com/591099 virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html [ Failure ] crbug.com/591099 virtual/android/fullscreen/exit-full-screen-iframe.html [ Crash Failure ] @@ -20285,7 +20358,6 @@ crbug.com/591099 virtual/android/fullscreen/video-controls-timeline.html [ Failure ] crbug.com/591099 virtual/android/fullscreen/video-fail-to-enter-full-screen.html [ Failure ] crbug.com/591099 virtual/android/media/mediadocument/media-document-with-download-button.html [ Failure ] -crbug.com/591099 virtual/android/fast/rootscroller/set-root-scroller.html [ Failure ] crbug.com/591099 virtual/display_list_2d_canvas/fast/canvas/2d.composite.globalAlpha.fillPath.html [ Crash ] crbug.com/591099 virtual/display_list_2d_canvas/fast/canvas/2d.fillText.gradient.html [ Crash ] crbug.com/591099 virtual/display_list_2d_canvas/fast/canvas/2d.text.draw.fill.maxWidth.gradient.html [ Crash ] @@ -21216,6 +21288,7 @@ crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/clip-descendents.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/clip-parent-reset.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html [ Failure ] +crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-layer-under-border-radius-under-composited-layer.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-nested-sticky-left.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-scrolling-paint-phases.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/compositing/overflow/content-gains-scrollbars.html [ Failure ] @@ -21400,7 +21473,7 @@ crbug.com/591099 virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing.html [ Timeout ] crbug.com/591099 virtual/service-worker-navigation-preload-disabled/webexposed/nonstable-css-properties.html [ Failure ] crbug.com/591099 virtual/service-worker-navigation-preload-disabled/webexposed/permissions-attribute.html [ Failure ] -crbug.com/591099 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/extendable-message-event.https.html [ Crash ] +crbug.com/591099 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/extendable-message-event.https.html [ Crash Timeout ] crbug.com/591099 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html [ Crash ] crbug.com/591099 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html [ Crash ] crbug.com/591099 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/activation.https.html [ Crash ] @@ -21533,7 +21606,6 @@ crbug.com/591099 virtual/threaded/animations/3d/state-at-end-event-transform.html [ Failure Pass ] crbug.com/591099 virtual/threaded/animations/animation-css-rule-types.html [ Failure ] crbug.com/591099 virtual/threaded/animations/animation-events-create.html [ Failure ] -crbug.com/591099 virtual/threaded/animations/prefixed/animation-inherit-initial-unprefixed.html [ Failure ] crbug.com/591099 virtual/threaded/animations/animations-parsing.html [ Timeout ] crbug.com/591099 virtual/threaded/animations/animations-responsive-to-color-change.html [ Crash ] crbug.com/591099 virtual/threaded/animations/clear-svg-animation-effects.html [ Crash ] @@ -21634,13 +21706,14 @@ crbug.com/591099 virtual/threaded/animations/interpolation/webkit-text-stroke-color-interpolation.html [ Crash ] crbug.com/591099 virtual/threaded/animations/interpolation/webkit-transform-interpolation.html [ Crash ] crbug.com/591099 virtual/threaded/animations/interpolation/webkit-transform-origin-interpolation.html [ Crash ] -crbug.com/591099 virtual/threaded/animations/prefixed/keyframes-cssom-prefixed-02.html [ Failure ] -crbug.com/591099 virtual/threaded/animations/prefixed/keyframes-cssom-unprefixed-02.html [ Failure ] crbug.com/591099 virtual/threaded/animations/keyframes-rule.html [ Failure ] crbug.com/591099 virtual/threaded/animations/lazy-detached-animation-stop.html [ Failure ] crbug.com/591099 virtual/threaded/animations/negative-delay-events.html [ Failure ] crbug.com/591099 virtual/threaded/animations/play-state-initially-paused-start-event.html [ Failure ] crbug.com/591099 virtual/threaded/animations/play-state.html [ Failure ] +crbug.com/591099 virtual/threaded/animations/prefixed/animation-inherit-initial-unprefixed.html [ Failure ] +crbug.com/591099 virtual/threaded/animations/prefixed/keyframes-cssom-prefixed-02.html [ Failure ] +crbug.com/591099 virtual/threaded/animations/prefixed/keyframes-cssom-unprefixed-02.html [ Failure ] crbug.com/591099 virtual/threaded/animations/responsive/d-responsive.html [ Crash ] crbug.com/591099 virtual/threaded/animations/responsive/line-height-responsive.html [ Pass Timeout ] crbug.com/591099 virtual/threaded/animations/rotate-transform-equivalent.html [ Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 47bee8c..83e8515 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -262,6 +262,7 @@ Bug(none) external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https.html [ Failure Timeout ] Bug(none) external/wpt/beacon/headers/header-referrer-strict-origin.https.html [ Failure Timeout ] Bug(none) external/wpt/beacon/headers/header-referrer-unsafe-url.https.html [ Failure Timeout ] +Bug(none) external/wpt/clear-site-data/navigation.https.html [ Timeout ] Bug(none) external/wpt/content-security-policy/child-src/child-src-about-blank-allowed-by-default.sub.html [ Failure Timeout ] Bug(none) external/wpt/content-security-policy/child-src/child-src-about-blank-allowed-by-scheme.sub.html [ Failure Timeout ] Bug(none) external/wpt/content-security-policy/child-src/child-src-allowed.sub.html [ Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 224f3344..6e6368b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -827,6 +827,8 @@ # Mac does not support fractional scale factor. crbug.com/567837 [ Mac ] virtual/scalefactor150/fast/hidpi/static [ Skip ] +crbug.com/739409 [ Linux ] fast/imagecapture/MediaStreamTrack-getConstraints.html [ Pass Crash ] + # TODO(oshima): Move the event scaling code to eventSender and remove this. crbug.com/567837 virtual/scalefactor200/fast/hidpi/static/mousewheel-scroll-amount.html [ Skip ] crbug.com/567837 virtual/scalefactor200/fast/hidpi/static/gesture-scroll-amount.html [ Skip ] @@ -866,6 +868,7 @@ # Mark as Failure until the development is done. crbug.com/739091 fast/forms/validation-bubble-appearance-edge.html [ Failure ] crbug.com/739091 fast/forms/validation-bubble-appearance-iframe.html [ Failure ] +crbug.com/739091 fast/forms/validation-bubble-appearance-rtl-ui.html [ Failure ] crbug.com/543110 [ Mac ] fast/text/international/text-shaping-arabic.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-relation-list-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-relation-list-properties.html new file mode 100644 index 0000000..5bfb6e0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/accessibility/aom-relation-list-properties.html
@@ -0,0 +1,239 @@ +<!DOCTYPE HTML> +<script src="../resources/gc.js"></script> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<!-- + +Accessibility Object Model +Explainer: https://github.com/WICG/aom/blob/master/explainer.md +Spec: https://wicg.github.io/aom/spec/ + +--> + +<script> +test(function(t) { + assert_true(internals.runtimeFlags.accessibilityObjectModelEnabled); +}, "Make sure that Accessibility Object Model is enabled"); +</script> + +<input id="input" aria-labeledby="l1 l2"> +<input id="input2" aria-labelledby="l1 l3"> +<label id="l1">L1</label> +<label id="l2">L2</label> +<label id="l3">L3</label> +<label id="l4">L4</label> + +<script> +test(function(t) { + var input = document.getElementById("input"); + var axInput = accessibilityController.accessibleElementById("input"); + assert_equals(axInput.name, "L1 L2"); + + var input2 = document.getElementById("input2"); + var axInput2 = accessibilityController.accessibleElementById("input2"); + assert_equals(axInput2.name, "L1 L3"); + + var l3 = document.getElementById("l3"); + var l4 = document.getElementById("l4"); + + input.accessibleNode.labeledBy = new AccessibleNodeList(); + input.accessibleNode.labeledBy.add(l3.accessibleNode); + + input2.accessibleNode.labeledBy = new AccessibleNodeList(); + input2.accessibleNode.labeledBy.add(l3.accessibleNode); + input2.accessibleNode.labeledBy.add(l4.accessibleNode); + + assert_equals(input2.accessibleNode.labeledBy.length, 2); + assert_equals(input2.accessibleNode.labeledBy[0], l3.accessibleNode); + assert_equals(input2.accessibleNode.labeledBy[1], l4.accessibleNode); + assert_equals(input2.accessibleNode.labeledBy[2], undefined); + + assert_equals(axInput.name, "L3"); + assert_equals(axInput2.name, "L3 L4"); + + input.accessibleNode.labeledBy = null; + assert_equals(axInput.name, "L1 L2"); + + input2.accessibleNode.labeledBy.remove(l3.accessibleNode); + assert_equals(axInput2.name, "L4"); + + input2.accessibleNode.labeledBy[0] = l2.accessibleNode; + assert_equals(axInput2.name, "L2"); + input2.accessibleNode.labeledBy[2] = l4.accessibleNode; + assert_equals(axInput2.name, "L2 L4"); +}, "AccessibleNode.labeledBy"); +</script> + +<input id="input3" aria-describedby="l1 l2"> + +<script> +test(function(t) { + var input = document.getElementById("input3"); + var axInput = accessibilityController.accessibleElementById("input3"); + assert_equals(axInput.description, "L1 L2"); + + var l3 = document.getElementById("l3"); + var l4 = document.getElementById("l4"); + + input.accessibleNode.describedBy = new AccessibleNodeList(); + input.accessibleNode.describedBy.add(l3.accessibleNode); + + input.accessibleNode.describedBy = new AccessibleNodeList(); + input.accessibleNode.describedBy.add(l3.accessibleNode); + input.accessibleNode.describedBy.add(l4.accessibleNode); + + assert_equals(input.accessibleNode.describedBy.length, 2); + assert_equals(input.accessibleNode.describedBy[0], l3.accessibleNode); + assert_equals(input.accessibleNode.describedBy[1], l4.accessibleNode); + assert_equals(input.accessibleNode.describedBy[2], undefined); + + assert_equals(axInput.description, "L3 L4"); + + input.accessibleNode.describedBy.remove(l3.accessibleNode); + assert_equals(axInput.description, "L4"); + + input.accessibleNode.describedBy[0] = l2.accessibleNode; + assert_equals(axInput.description, "L2"); + input.accessibleNode.describedBy[2] = l4.accessibleNode; + assert_equals(axInput.description, "L2 L4"); + + input.accessibleNode.describedBy = null; + assert_equals(axInput.description, "L1 L2"); +}, "AccessibleNode.describedBy"); +</script> + +<ul id="tablist_1" role="tablist"> +<li id="tab_1" role="tab" aria-controls="panel_1 panel_2"></li> +</ul> + +<div id="panel_1" role="tabpanel">Panel 1</div> +<div id="panel_2" role="tabpanel">Panel 2</div> +<div id="panel_3" role="tabpanel">Panel 3</div> +<div id="panel_4" role="tabpanel">Panel 4</div> + +<p id="description"></p> +<div id="console"></div> + +<script> +test(function(t) { + var axTab1 = accessibilityController.accessibleElementById("tablist_1").childAtIndex(0); + var axPanel1 = accessibilityController.accessibleElementById("panel_1"); + var axPanel2 = accessibilityController.accessibleElementById("panel_2"); + var axPanel3 = accessibilityController.accessibleElementById("panel_3"); + var axPanel4 = accessibilityController.accessibleElementById("panel_4"); + + assert_true(axTab1.ariaControlsElementAtIndex(0).isEqual(axPanel1)); + assert_true(axTab1.ariaControlsElementAtIndex(1).isEqual(axPanel2)); + + var tab1 = document.getElementById("tablist_1").firstElementChild; + var panel3 = document.getElementById("panel_3"); + var panel4 = document.getElementById("panel_4"); + tab1.accessibleNode.controls = new AccessibleNodeList(); + tab1.accessibleNode.controls[0] = panel3.accessibleNode; + + assert_true(axTab1.ariaControlsElementAtIndex(0).isEqual(axPanel3)); + assert_equals(axTab1.ariaControlsElementAtIndex(1), undefined); + + tab1.accessibleNode.controls[1] = panel4.accessibleNode; + + assert_true(axTab1.ariaControlsElementAtIndex(0).isEqual(axPanel3)); + assert_true(axTab1.ariaControlsElementAtIndex(1).isEqual(axPanel4)); + + tab1.accessibleNode.controls = null; + + assert_true(axTab1.ariaControlsElementAtIndex(0).isEqual(axPanel1)); + assert_true(axTab1.ariaControlsElementAtIndex(1).isEqual(axPanel2)); +}, "AccessibleNode.controls"); +</script> + +<h1 id="item1" aria-flowto="item2 item3"></h1> + +<div id="item2">Content 2</div> +<div id="item3">Content 3</div> +<div id="item4">Content 4</div> + +<p id="description"></p> +<div id="console"></div> + +<script> +test(function(t) { + var axItem1 = accessibilityController.accessibleElementById("item1"); + var axItem2 = accessibilityController.accessibleElementById("item2"); + var axItem3 = accessibilityController.accessibleElementById("item3"); + var axItem4 = accessibilityController.accessibleElementById("item4"); + + assert_true(axItem1.ariaFlowToElementAtIndex(0).isEqual(axItem2)); + assert_true(axItem1.ariaFlowToElementAtIndex(1).isEqual(axItem3)); + + var item1 = document.getElementById("item1"); + var item2 = document.getElementById("item2"); + var item3 = document.getElementById("item3"); + var item4 = document.getElementById("item4"); + + item1.accessibleNode.flowTo = new AccessibleNodeList(); + item1.accessibleNode.flowTo.add(item4.accessibleNode); + + assert_true(axItem1.ariaFlowToElementAtIndex(0).isEqual(axItem4)); + assert_equals(axItem1.ariaFlowToElementAtIndex(1), undefined); + + item1.accessibleNode.flowTo.add(item2.accessibleNode); + + assert_true(axItem1.ariaFlowToElementAtIndex(1).isEqual(axItem2)); + + item1.accessibleNode.flowTo = null; + + assert_true(axItem1.ariaFlowToElementAtIndex(0).isEqual(axItem2)); + assert_true(axItem1.ariaFlowToElementAtIndex(1).isEqual(axItem3)); +}, "AccessibleNode.flowTo"); +</script> + +<div class="container"> + <ul id="list1" role="listbox" aria-owns="listitem3"> + <li role="option">One</li> + <li role="option">Two</li> + </ul> + <ul role="listbox" id="list2"> + <li role="option" id="listitem3">Three</li> + <li role="option" id="listitem4">Four</li> + </ul> +</div> + +<script> +test(function(t) +{ + var axList1 = accessibilityController.accessibleElementById("list1"); + assert_equals(axList1.role, "AXRole: AXListBox"); + assert_equals(axList1.childrenCount, 3); + + var axListitem = axList1.childAtIndex(0); + assert_equals(axList1.childAtIndex(0).name, "One"); + assert_equals(axList1.childAtIndex(1).name, "Two"); + assert_equals(axList1.childAtIndex(2).name, "Three"); + + var axList2 = accessibilityController.accessibleElementById("list2"); + assert_equals(axList2.role, "AXRole: AXListBox"); + assert_equals(axList2.childrenCount, 1); + assert_equals(axList2.childAtIndex(0).name, "Four"); + + var list1 = document.getElementById("list1"); + var item4 = document.getElementById("item4"); + + list1.accessibleNode.owns = new AccessibleNodeList(); + assert_equals(axList1.childrenCount, 2); +/** + + + list1.accessibleNode.owns[0] = item4.accessibleNode; + assert_equals(axList1.childrenCount, 3); + assert_equals(axList1.childAtIndex(0).name, "One"); + assert_equals(axList1.childAtIndex(1).name, "Two"); +assert_equals(axList1.childAtIndex(2).name, "Four"); +**/ +}, "AccessibleNode.owns"); +</script> + +<script> +if (window.testRunner) + document.body.className = "hideAllContainers"; +</script>
diff --git a/third_party/WebKit/LayoutTests/accessibility/input-mixed.html b/third_party/WebKit/LayoutTests/accessibility/input-mixed.html index 68e2f77..b62b689 100644 --- a/third_party/WebKit/LayoutTests/accessibility/input-mixed.html +++ b/third_party/WebKit/LayoutTests/accessibility/input-mixed.html
@@ -54,9 +54,9 @@ test(function(t) { var ax = axElementById("element3"); - assert_equals(ax.checked, "mixed"); + assert_equals(ax.checked, "false"); }, "A native radio that in a group with nothing checked" + - " must have the mixed state"); + " must appear unchecked, not mixed"); test(function(t) { var ax = axElementById("element4");
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.html b/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.html deleted file mode 100644 index b4f933b5..0000000 --- a/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.html +++ /dev/null
@@ -1,33 +0,0 @@ -<!DOCTYPE HTML> -<style> -#scroller { - width: 100px; - height: 100px; - border: 1px solid black; - overflow: scroll; - border-radius: 1px; -} - -#scrolled { - width: 60px; - height: 300px; - border: 1px solid black; - background: papayawhip; -} - -#composited { - width: 10px; - height: 10px; - will-change: transform; - background: green; - border: 2px solid orange; -} -</style> -<div id="scroller"> - <div id="scrolled"></div> - <div id="composited"></div> -</div> -<script> -if (window.internals) - internals.settings.setPreferCompositingToLCDTextEnabled(false); -</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.png b/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.png new file mode 100644 index 0000000..1626ec0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.txt b/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.txt new file mode 100644 index 0000000..591a94a --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.txt
@@ -0,0 +1,10 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x118 + LayoutBlockFlow {HTML} at (0,0) size 800x118 + LayoutBlockFlow {BODY} at (8,8) size 784x102 +layer at (8,8) size 102x102 clip at (9,9) size 85x85 scrollHeight 316 + LayoutBlockFlow {DIV} at (0,0) size 102x102 [border: (1px solid #000000)] + LayoutBlockFlow {DIV} at (1,1) size 62x302 [bgcolor=#FFEFD5] [border: (1px solid #000000)] +layer at (9,311) size 14x14 backgroundClip at (9,9) size 85x85 clip at (9,9) size 85x85 + LayoutBlockFlow {DIV} at (1,303) size 14x14 [bgcolor=#008000] [border: (2px solid #FFA500)]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius-expected.txt b/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius-expected.txt index decd541..e5ce051 100644 --- a/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius-expected.txt +++ b/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius-expected.txt
@@ -1,3 +1,3 @@ No border radius (should be using composited scrolling): Pass. -Has border radius (should not be using composited scrolling): Pass. +Has border radius (should also be using composited scrolling): Pass.
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius.html b/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius.html index 5729ca08..de4fa85c 100644 --- a/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius.html +++ b/third_party/WebKit/LayoutTests/compositing/overflow/scroller-with-border-radius.html
@@ -49,11 +49,11 @@ document.getElementById("scroller").style.borderRadius = '5px'; requestAnimationFrame(function() { if (window.internals) { - result += "Has border radius (should not be using composited scrolling): "; + result += "Has border radius (should also be using composited scrolling): "; if (!isUsingCompositedScrolling(JSON.parse(window.internals.layerTreeAsText(document)))) - result += "Pass.\n"; + result += "Fail.\n"; else - result += "Fail.\n" + result += "Pass.\n" } if (window.testRunner) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/resources/worker-with-performance-observer.js b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/resources/worker-with-performance-observer.js new file mode 100644 index 0000000..a72fe81 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/resources/worker-with-performance-observer.js
@@ -0,0 +1,6 @@ +try { + new PerformanceObserver(() => true); + postMessage("SUCCESS"); +} catch (ex) { + postMessage("FAILURE"); +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/worker-with-performance-observer-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/worker-with-performance-observer-expected.txt new file mode 100644 index 0000000..b319839c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/worker-with-performance-observer-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Worker: Test Performance Observer inside a worker. assert_equals: expected "SUCCESS" but got "FAILURE" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/worker-with-performance-observer.html b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/worker-with-performance-observer.html new file mode 100644 index 0000000..fc92bc9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/worker-with-performance-observer.html
@@ -0,0 +1,18 @@ +<!doctype html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +async_test(function(t) { + const worker = new Worker("resources/worker-with-performance-observer.js"); + worker.onmessage = function(event) { + t.step(() => assert_equals(event.data, 'SUCCESS')); + t.done(); + } +}, 'Worker: Test Performance Observer inside a worker.'); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/chooser_service.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/chooser_service.mojom.js index f125fac..30bba4b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/chooser_service.mojom.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/chooser_service.mojom.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + 'use strict'; (function() { @@ -18,21 +19,19 @@ var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; + + var exports = mojo.internal.exposeNamespace('device.mojom'); var device$ = mojo.internal.exposeNamespace('device.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( - 'device/usb/public/interfaces/device.mojom', - new URL('device.mojom.js', - document.currentScript.src).href); + 'device/usb/public/interfaces/device.mojom', 'device.mojom.js'); } var device_manager$ = mojo.internal.exposeNamespace('device.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( - 'device/usb/public/interfaces/device_manager.mojom', - new URL('device_manager.mojom.js', - document.currentScript.src).href); + 'device/usb/public/interfaces/device_manager.mojom', 'device_manager.mojom.js'); } @@ -274,7 +273,6 @@ }; UsbChooserServiceStub.prototype.validator = validateUsbChooserServiceRequest; UsbChooserServiceProxy.prototype.validator = validateUsbChooserServiceResponse; - var exports = mojo.internal.exposeNamespace("device.mojom"); exports.UsbChooserService = UsbChooserService; exports.UsbChooserServicePtr = UsbChooserServicePtr; exports.UsbChooserServiceAssociatedPtr = UsbChooserServiceAssociatedPtr;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device.mojom.js index 5e618ec..ce5660cd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device.mojom.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device.mojom.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + 'use strict'; (function() { @@ -19,6 +20,14 @@ var codec = mojo.internal; var validator = mojo.internal; + var exports = mojo.internal.exposeNamespace('device.mojom'); + var string16$ = + mojo.internal.exposeNamespace('mojo.common.mojom'); + if (mojo.config.autoLoadMojomDeps) { + mojo.internal.loadMojomIfNecessary( + 'mojo/common/string16.mojom', '../../../../mojo/common/string16.mojom.js'); + } + var UsbOpenDeviceError = {}; UsbOpenDeviceError.OK = 0; @@ -290,7 +299,7 @@ // validate UsbAlternateInterfaceInfo.interfaceName - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, string16$.String16, true); if (err !== validator.validationError.NONE) return err; @@ -319,7 +328,7 @@ decoder.skip(1); decoder.skip(1); decoder.skip(1); - val.interfaceName = decoder.decodeStruct(codec.NullableString); + val.interfaceName = decoder.decodeStructPointer(string16$.String16); val.endpoints = decoder.decodeArrayPointer(new codec.PointerTo(UsbEndpointInfo)); return val; }; @@ -336,7 +345,7 @@ encoder.skip(1); encoder.skip(1); encoder.skip(1); - encoder.encodeStruct(codec.NullableString, val.interfaceName); + encoder.encodeStructPointer(string16$.String16, val.interfaceName); encoder.encodeArrayPointer(new codec.PointerTo(UsbEndpointInfo), val.endpoints); }; function UsbInterfaceInfo(values) { @@ -448,7 +457,7 @@ // validate UsbConfigurationInfo.configurationName - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, string16$.String16, true); if (err !== validator.validationError.NONE) return err; @@ -477,7 +486,7 @@ decoder.skip(1); decoder.skip(1); decoder.skip(1); - val.configurationName = decoder.decodeStruct(codec.NullableString); + val.configurationName = decoder.decodeStructPointer(string16$.String16); val.interfaces = decoder.decodeArrayPointer(new codec.PointerTo(UsbInterfaceInfo)); return val; }; @@ -494,7 +503,7 @@ encoder.skip(1); encoder.skip(1); encoder.skip(1); - encoder.encodeStruct(codec.NullableString, val.configurationName); + encoder.encodeStructPointer(string16$.String16, val.configurationName); encoder.encodeArrayPointer(new codec.PointerTo(UsbInterfaceInfo), val.interfaces); }; function UsbDeviceInfo(values) { @@ -563,21 +572,21 @@ // validate UsbDeviceInfo.manufacturerName - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, true) + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, string16$.String16, true); if (err !== validator.validationError.NONE) return err; // validate UsbDeviceInfo.productName - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 32, true) + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 32, string16$.String16, true); if (err !== validator.validationError.NONE) return err; // validate UsbDeviceInfo.serialNumber - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 40, true) + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, string16$.String16, true); if (err !== validator.validationError.NONE) return err; @@ -614,9 +623,9 @@ val.activeConfiguration = decoder.decodeStruct(codec.Uint8); decoder.skip(1); decoder.skip(1); - val.manufacturerName = decoder.decodeStruct(codec.NullableString); - val.productName = decoder.decodeStruct(codec.NullableString); - val.serialNumber = decoder.decodeStruct(codec.NullableString); + val.manufacturerName = decoder.decodeStructPointer(string16$.String16); + val.productName = decoder.decodeStructPointer(string16$.String16); + val.serialNumber = decoder.decodeStructPointer(string16$.String16); val.configurations = decoder.decodeArrayPointer(new codec.PointerTo(UsbConfigurationInfo)); return val; }; @@ -640,9 +649,9 @@ encoder.encodeStruct(codec.Uint8, val.activeConfiguration); encoder.skip(1); encoder.skip(1); - encoder.encodeStruct(codec.NullableString, val.manufacturerName); - encoder.encodeStruct(codec.NullableString, val.productName); - encoder.encodeStruct(codec.NullableString, val.serialNumber); + encoder.encodeStructPointer(string16$.String16, val.manufacturerName); + encoder.encodeStructPointer(string16$.String16, val.productName); + encoder.encodeStructPointer(string16$.String16, val.serialNumber); encoder.encodeArrayPointer(new codec.PointerTo(UsbConfigurationInfo), val.configurations); }; function UsbControlTransferParams(values) { @@ -3432,7 +3441,6 @@ }; UsbDeviceStub.prototype.validator = validateUsbDeviceRequest; UsbDeviceProxy.prototype.validator = validateUsbDeviceResponse; - var exports = mojo.internal.exposeNamespace("device.mojom"); exports.UsbOpenDeviceError = UsbOpenDeviceError; exports.UsbTransferDirection = UsbTransferDirection; exports.UsbControlTransferType = UsbControlTransferType;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device_manager.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device_manager.mojom.js index 5a03393..99ebd85 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device_manager.mojom.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/device_manager.mojom.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + 'use strict'; (function() { @@ -18,13 +19,19 @@ var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; + + var exports = mojo.internal.exposeNamespace('device.mojom'); var device$ = mojo.internal.exposeNamespace('device.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( - 'device/usb/public/interfaces/device.mojom', - new URL('device.mojom.js', - document.currentScript.src).href); + 'device/usb/public/interfaces/device.mojom', 'device.mojom.js'); + } + var string16$ = + mojo.internal.exposeNamespace('mojo.common.mojom'); + if (mojo.config.autoLoadMojomDeps) { + mojo.internal.loadMojomIfNecessary( + 'mojo/common/string16.mojom', '../../../../mojo/common/string16.mojom.js'); } @@ -81,7 +88,7 @@ // validate UsbDeviceFilter.serialNumber - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, string16$.String16, true); if (err !== validator.validationError.NONE) return err; @@ -106,7 +113,7 @@ val.productId = decoder.decodeStruct(codec.Uint16); val.subclassCode = decoder.decodeStruct(codec.Uint8); val.protocolCode = decoder.decodeStruct(codec.Uint8); - val.serialNumber = decoder.decodeStruct(codec.NullableString); + val.serialNumber = decoder.decodeStructPointer(string16$.String16); return val; }; @@ -126,7 +133,7 @@ encoder.encodeStruct(codec.Uint16, val.productId); encoder.encodeStruct(codec.Uint8, val.subclassCode); encoder.encodeStruct(codec.Uint8, val.protocolCode); - encoder.encodeStruct(codec.NullableString, val.serialNumber); + encoder.encodeStructPointer(string16$.String16, val.serialNumber); }; function UsbEnumerationOptions(values) { this.initDefaults_(); @@ -838,7 +845,6 @@ }; UsbDeviceManagerClientStub.prototype.validator = validateUsbDeviceManagerClientRequest; UsbDeviceManagerClientProxy.prototype.validator = null; - var exports = mojo.internal.exposeNamespace("device.mojom"); exports.UsbDeviceFilter = UsbDeviceFilter; exports.UsbEnumerationOptions = UsbEnumerationOptions; exports.UsbDeviceManager = UsbDeviceManager;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/mojo_bindings.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/mojo_bindings.js index af8d859..67d6a88 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/mojo_bindings.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/mojo_bindings.js
@@ -34,18 +34,25 @@ // you merge bar.mojom.js and foo.mojom.js into a single file. // // Performance tip: Avoid loading the same mojom.js file multiple times. - // Assume that |autoLoadMojomDeps| is set to true: - // <!-- No duplicate loading; recommended. --> + // Assume that |autoLoadMojomDeps| is set to true, + // + // <!-- + // (This comment tag is necessary on IOS to avoid interpreting the closing + // script tags in the example.) + // + // No duplicate loading; recommended: // <script src="http://example.org/scripts/b/c/foo.mojom.js"></script> // - // <!-- No duplicate loading, although unnecessary. --> + // No duplicate loading, although unnecessary: // <script src="http://example.org/scripts/b/d/bar.mojom.js"></script> // <script src="http://example.org/scripts/b/c/foo.mojom.js"></script> // - // <!-- Load bar.mojom.js twice; should be avoided. --> + // Load bar.mojom.js twice; should be avoided: // <script src="http://example.org/scripts/b/c/foo.mojom.js"></script> // <script src="http://example.org/scripts/b/d/bar.mojom.js"></script> - autoLoadMojomDeps: false + // + // --> + autoLoadMojomDeps: true }; (function() { @@ -92,14 +99,22 @@ mojomRegistry.set(id, LoadState.LOADED); } - function loadMojomIfNecessary(id, url) { + function loadMojomIfNecessary(id, relativePath) { if (mojomRegistry.has(id)) { return; } + if (internal.global.document === undefined) { + throw new Error( + 'Mojom dependency autoloading is not implemented in workers. ' + + 'Please see config variable mojo.config.autoLoadMojomDeps for more ' + + 'details.'); + } + markMojomPendingLoad(id); + var url = new URL(relativePath, document.currentScript.src).href; internal.global.document.write('<script type="text/javascript" src="' + - url + '"></script>'); + url + '"><' + '/script>'); } internal.exposeNamespace = exposeNamespace; @@ -3957,6 +3972,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + 'use strict'; (function() { @@ -3974,6 +3990,8 @@ var codec = mojo.internal; var validator = mojo.internal; + var exports = mojo.internal.exposeNamespace('mojo.interfaceControl2'); + var kRunMessageId = 0xFFFFFFFF; var kRunOrClosePipeMessageId = 0xFFFFFFFE; @@ -4750,7 +4768,6 @@ }; RunOrClosePipeInput.encodedSize = 16; - var exports = mojo.internal.exposeNamespace("mojo.interfaceControl2"); exports.kRunMessageId = kRunMessageId; exports.kRunOrClosePipeMessageId = kRunOrClosePipeMessageId; exports.RunMessageParams = RunMessageParams; @@ -4767,6 +4784,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + 'use strict'; (function() { @@ -4784,6 +4802,8 @@ var codec = mojo.internal; var validator = mojo.internal; + var exports = mojo.internal.exposeNamespace('mojo.pipeControl2'); + var kRunOrClosePipeMessageId = 0xFFFFFFFE; @@ -5101,10 +5121,9 @@ }; RunOrClosePipeInput.encodedSize = 16; - var exports = mojo.internal.exposeNamespace("mojo.pipeControl2"); exports.kRunOrClosePipeMessageId = kRunOrClosePipeMessageId; exports.RunOrClosePipeMessageParams = RunOrClosePipeMessageParams; exports.DisconnectReason = DisconnectReason; exports.PeerAssociatedEndpointClosedEvent = PeerAssociatedEndpointClosedEvent; exports.RunOrClosePipeInput = RunOrClosePipeInput; -})(); +})(); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/string16.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/string16.mojom.js new file mode 100644 index 0000000..058956b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/string16.mojom.js
@@ -0,0 +1,159 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +'use strict'; +if ((typeof mojo !== 'undefined') && mojo.internal && mojo.config) { + +(function() { + var mojomId = 'mojo/common/string16.mojom'; + if (mojo.internal.isMojomLoaded(mojomId)) { + console.warn('The following mojom is loaded multiple times: ' + mojomId); + return; + } + mojo.internal.markMojomLoaded(mojomId); + + // TODO(yzshen): Define these aliases to minimize the differences between the + // old/new modes. Remove them when the old mode goes away. + var bindings = mojo; + var associatedBindings = mojo; + var codec = mojo.internal; + var validator = mojo.internal; + + var exports = mojo.internal.exposeNamespace('mojo.common.mojom'); + + + + function String16(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + String16.prototype.initDefaults_ = function() { + this.data = null; + }; + String16.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + String16.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + + // validate String16.data + err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 2, codec.Uint16, false, [0], 0); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + String16.encodedSize = codec.kStructHeaderSize + 8; + + String16.decode = function(decoder) { + var packed; + var val = new String16(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.data = decoder.decodeArrayPointer(codec.Uint16); + return val; + }; + + String16.encode = function(encoder, val) { + var packed; + encoder.writeUint32(String16.encodedSize); + encoder.writeUint32(0); + encoder.encodeArrayPointer(codec.Uint16, val.data); + }; + exports.String16 = String16; +})(); +} + +if ((typeof mojo === 'undefined') || !mojo.internal || !mojo.config) { + +define("mojo/common/string16.mojom", [ + "mojo/public/js/associated_bindings", + "mojo/public/js/bindings", + "mojo/public/js/codec", + "mojo/public/js/core", + "mojo/public/js/validator", +], function(associatedBindings, bindings, codec, core, validator) { + var exports = {}; + + function String16(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + String16.prototype.initDefaults_ = function() { + this.data = null; + }; + String16.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + String16.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + + // validate String16.data + err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 2, codec.Uint16, false, [0], 0); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + String16.encodedSize = codec.kStructHeaderSize + 8; + + String16.decode = function(decoder) { + var packed; + var val = new String16(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.data = decoder.decodeArrayPointer(codec.Uint16); + return val; + }; + + String16.encode = function(encoder, val) { + var packed; + encoder.writeUint32(String16.encodedSize); + encoder.writeUint32(0); + encoder.encodeArrayPointer(codec.Uint16, val.data); + }; + exports.String16 = String16; + + return exports; +}); +} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webusb-test.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webusb-test.js index 97eac81..d700538b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webusb-test.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webusb-test.js
@@ -19,6 +19,21 @@ chooserCrossFrameProxy: null, }; +// Converts an ECMAScript String object to an instance of +// mojo.common.mojom.String16. +function mojoString16ToString(string16) { + return String.fromCharCode.apply(null, string16.data); +} + +// Converts an instance of mojo.common.mojom.String16 to an ECMAScript String. +function stringToMojoString16(string) { + let array = new Array(string.length); + for (var i = 0; i < string.length; ++i) { + array[i] = string.charCodeAt(i); + } + return { data: array } +} + function fakeDeviceInitToDeviceInfo(guid, init) { let deviceInfo = { guid: guid + "", @@ -33,16 +48,16 @@ deviceVersionMajor: init.deviceVersionMajor, deviceVersionMinor: init.deviceVersionMinor, deviceVersionSubminor: init.deviceVersionSubminor, - manufacturerName: init.manufacturerName, - productName: init.productName, - serialNumber: init.serialNumber, + manufacturerName: stringToMojoString16(init.manufacturerName), + productName: stringToMojoString16(init.productName), + serialNumber: stringToMojoString16(init.serialNumber), activeConfiguration: init.activeConfigurationValue, configurations: [] }; init.configurations.forEach(config => { var configInfo = { configurationValue: config.configurationValue, - configurationName: config.configurationName, + configurationName: stringToMojoString16(config.configurationName), interfaces: [] }; config.interfaces.forEach(iface => { @@ -56,7 +71,7 @@ classCode: alternate.interfaceClass, subclassCode: alternate.interfaceSubclass, protocolCode: alternate.interfaceProtocol, - interfaceName: alternate.interfaceName, + interfaceName: stringToMojoString16(alternate.interfaceName), endpoints: [] }; alternate.endpoints.forEach(endpoint => { @@ -115,7 +130,7 @@ if (input.hasProtocolCode) output.protocolCode = input.protocolCode; if (input.serialNumber) - output.serialNumber = input.serialNumber; + output.serialNumber = mojoString16ToString(input.serialNumber); return output; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/usb-helpers.js b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/usb-helpers.js index 452c04f..989e8f1f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/usb-helpers.js +++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/usb-helpers.js
@@ -18,6 +18,7 @@ let chain = Promise.resolve(); [ '/resources/chromium/mojo_bindings.js', + '/resources/chromium/string16.mojom.js', '/resources/chromium/device.mojom.js', '/resources/chromium/device_manager.mojom.js', '/resources/chromium/chooser_service.mojom.js',
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.png index ec414a90..b1251809 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.png +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.txt index 36877905..69e3b0b 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge-expected.txt
@@ -1,15 +1,3 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x50 - LayoutBlockFlow {HTML} at (0,0) size 800x50 - LayoutBlockFlow {BODY} at (8,16) size 784x18 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 377x18 - text run at (0,0) width 377: "Check if a validation bubble is shown at a correct position." -layer at (661,573) size 131x19 clip at (663,575) size 127x15 - LayoutTextControl (positioned) {INPUT} at (661,573) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] -layer at (664,576) size 125x13 - LayoutBlockFlow {DIV} at (3,3) size 125x13 - LayoutText {#text} at (0,0) size 19x13 - text run at (0,0) width 19: "abc" -caret: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 3 {INPUT} of body +Check if a validation bubble is shown at a correct position. + +
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge.html b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge.html index 3411897..b86c1ce 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge.html +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-edge.html
@@ -3,6 +3,11 @@ <p>Check if a validation bubble is shown at a correct position.</p> <input pattern="\d{4}" title="Please specify four digits." value="abc" style="position:absolute; right:8px; bottom: 8px;"> <script> +if (window.testRunner) { + // Layout tree dump doesn't matter. + testRunner.dumpAsTextWithPixelResults(); +} + document.querySelector('input').reportValidity(); </script> <body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.png index 80755b9..4aedf2ad 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.png +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.txt index 4946765..50e0f46 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe-expected.txt
@@ -1,27 +1,3 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x216 - LayoutBlockFlow {HTML} at (0,0) size 800x216 - LayoutBlockFlow {BODY} at (8,16) size 784x192 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 406x18 - text run at (0,0) width 406: "Check if a validation bubble is shown over IFRAME boundary." - LayoutBlockFlow (anonymous) at (0,34) size 784x158 - LayoutText {#text} at (0,0) size 0x0 -layer at (8,50) size 304x154 - LayoutIFrame {IFRAME} at (0,0) size 304x154 [border: (2px inset #EEEEEE)] - layer at (0,0) size 300x150 - LayoutView at (0,0) size 300x150 - layer at (0,0) size 300x68 - LayoutBlockFlow {HTML} at (0,0) size 300x68 - LayoutBlockFlow {BODY} at (8,16) size 284x36 - LayoutBlockFlow {P} at (0,0) size 284x36 - LayoutText {#text} at (0,0) size 269x36 - text run at (0,0) width 269: "Check if a validation bubble is shown at a" - text run at (0,18) width 104: "correct position." - layer at (161,123) size 131x19 clip at (163,125) size 127x15 - LayoutTextControl (positioned) {INPUT} at (161,123) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - layer at (164,126) size 125x13 - LayoutBlockFlow {DIV} at (3,3) size 125x13 - LayoutText {#text} at (0,0) size 19x13 - text run at (0,0) width 19: "abc" +Check if a validation bubble is shown over IFRAME boundary. + +
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe.html b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe.html index a62cdbf..5967a68 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe.html +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-iframe.html
@@ -2,4 +2,10 @@ <body> <p>Check if a validation bubble is shown over IFRAME boundary.</p> <iframe src="validation-bubble-appearance-edge.html"></iframe> -<body> +<script> +if (window.testRunner) { + // Layout tree dump doesn't matter. + testRunner.dumpAsTextWithPixelResults(); +} +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui-expected.png new file mode 100644 index 0000000..0d30cd6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui-expected.txt new file mode 100644 index 0000000..98cf1f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui-expected.txt
@@ -0,0 +1,3 @@ +Check if a validation bubble is shown at a correct position in RTL UI. + +
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui.html b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui.html new file mode 100644 index 0000000..53e1057 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/validation-bubble-appearance-rtl-ui.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<body> +<p>Check if a validation bubble is shown at a correct position in RTL UI.</p> +<input pattern="\d{4}" title="Please specify four digits." value="abc" style="margin-left: 30%;"> +<script> +if (window.testRunner) { + // Layout tree dump doesn't matter. + testRunner.dumpAsTextWithPixelResults(); +} + +internals.setUserPreferredLanguages(['ar']); +document.querySelector('input').reportValidity(); +</script> +<body>
diff --git a/third_party/WebKit/LayoutTests/fast/history/scroll-restoration/scroll-restoration-same-doc.html b/third_party/WebKit/LayoutTests/fast/history/scroll-restoration/scroll-restoration-same-doc.html new file mode 100644 index 0000000..d59e3db --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/history/scroll-restoration/scroll-restoration-same-doc.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> + +<style> + #bigdiv { + width: 200px; + height: 1100px; + } +</style> + +<div id="bigdiv"> +</div> + +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> + +<script> + 'use strict'; + const bigdiv = document.getElementById("bigdiv"); + + async_test((t) => { + // 1. scroll to bottom. + window.scrollBy(0, 100); + assert_equals(window.scrollY, 100); + + // 2. remove bigdiv and push state. + history.pushState(1, null, "page2.html"); + document.body.removeChild(bigdiv); + assert_equals(window.scrollY, 0); + + window.onpopstate = () => { + document.body.appendChild(bigdiv); + setTimeout(() => { + t.step(() => { + assert_equals(window.scrollY, 100); + }); + t.done(); + }, 0); + }; + + // 3. navigation back. page should restore scroll position to 100, see below. + history.back(); + }, "load-in-same-doc-and-change-DOM-onpopstate"); +</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.png new file mode 100644 index 0000000..281a6bd --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/overflow/respect-clip-for-non-composited-scrollers-when-prefering-compositing-over-lcd-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/budget/budget-service-mock.js b/third_party/WebKit/LayoutTests/http/tests/budget/budget-service-mock.js index 60ceac0..ba8b78f 100644 --- a/third_party/WebKit/LayoutTests/http/tests/budget/budget-service-mock.js +++ b/third_party/WebKit/LayoutTests/http/tests/budget/budget-service-mock.js
@@ -16,12 +16,16 @@ const [budgetService, bindings] = mojo.modules; class BudgetServiceMock { - constructor(interfaceProvider) { - interfaceProvider.addInterfaceOverrideForTesting( + constructor() { + // Register process-wide (worker) interface override. + mojo.interfaces.addInterfaceOverrideForTesting( budgetService.BudgetService.name, handle => this.bindingSet_.addBinding(this, handle)); - this.interfaceProvider_ = interfaceProvider; + // Register frame interface override. + mojo.frameInterfaces.addInterfaceOverrideForTesting( + budgetService.BudgetService.name, + handle => this.bindingSet_.addBinding(this, handle)); // Values to return for the next getBudget and getCost calls. this.cost_ = {}; @@ -88,5 +92,5 @@ return Promise.resolve({ error_type: this.error_, success: this.success_ }); } } - return new BudgetServiceMock(mojo.interfaces); + return new BudgetServiceMock(); });
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/interception-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/interception-test.js index ef14c50..59750ec 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/interception-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/resources/interception-test.js
@@ -83,14 +83,14 @@ } InspectorTest.log("Network agent enabled"); InspectorTest.sendCommand( - "Network.enableRequestInterception", {"enabled": true}, - didEnableRequestInterception); + "Network.setRequestInterceptionEnabled", {"enabled": true}, + didSetRequestInterceptionEnabled); } - function didEnableRequestInterception(messageObject) + function didSetRequestInterceptionEnabled(messageObject) { if (messageObject.error) { - completeTest("FAIL: Couldn't enable fetch interception" + + completeTest("FAIL: Couldn't enable fetch interception " + messageObject.error.message); return; } @@ -256,7 +256,7 @@ InspectorTest.disableRequestInterception = function(event) { var id = canonicalId(event.params.interceptionId); log(id, "----- disableRequestInterception -----"); - InspectorTest.sendCommand("Network.enableRequestInterception", { + InspectorTest.sendCommand("Network.setRequestInterceptionEnabled", { "enabled": false, }); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt new file mode 100644 index 0000000..98696d4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt
@@ -0,0 +1,5 @@ +CONSOLE ERROR: Failed to find a valid digest in the 'integrity' attribute for resource 'http://127.0.0.1:8000/security/subresourceIntegrity/resources/clear-integrity-attribute.js' with computed SHA-256 integrity 'yM5ZyzNsyKfaXRY78zSGapeQKtl0oGdpPpYxgwl8XW8='. The resource has been blocked. +ALERT: FAIL +This test passes if only one 'FAIL' alert appears. + +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/clear-integrity-attribute.html b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/clear-integrity-attribute.html new file mode 100644 index 0000000..067c9c5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/clear-integrity-attribute.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<body onload="runTest()"> + <script> + if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.waitUntilDone(); + } + function runTest() { + var script = document.createElement('script'); + script.onload = function() { testRunner.notifyDone(); }; + script.onerror = function() { testRunner.notifyDone(); }; + script.setAttribute('integrity', "sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE="); + script.src = "resources/clear-integrity-attribute.js"; + document.body.appendChild(script); + } + </script> + <p> + This test passes if only one 'FAIL' alert appears. + </p> + <iframe src="http://127.0.0.1:8000/security/subresourceIntegrity/resources/clear-integrity-attribute.html"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/clear-integrity-attribute.html b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/clear-integrity-attribute.html new file mode 100644 index 0000000..898e7df --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/clear-integrity-attribute.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> + <head> + <title></title> + <script id="script0" defer src="http://127.0.0.1:8000/security/subresourceIntegrity/resources/clear-integrity-attribute.js" integrity="sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE="></script> + <script> + document.getElementById('script0').setAttribute('integrity', ''); + </script> + </head> + <body> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/clear-integrity-attribute.js b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/clear-integrity-attribute.js new file mode 100644 index 0000000..2462b4b --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/clear-integrity-attribute.js
@@ -0,0 +1 @@ +alert('FAIL');
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.html b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.html new file mode 100644 index 0000000..401644b --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> + <title></title> + <script src="shared-with-xhtml.js" integrity="sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE="></script> +</head> +<body> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.js b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.js new file mode 100644 index 0000000..2462b4b --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.js
@@ -0,0 +1 @@ +alert('FAIL');
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.xhtml b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.xhtml new file mode 100644 index 0000000..403a6a0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/shared-with-xhtml.xhtml
@@ -0,0 +1,11 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html lang="EN" dir="ltr" xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="content-type" content="text/xml; charset=utf-8" /> + <title></title> + <script src="http://127.0.0.1:8000/security/subresourceIntegrity/resources/shared-with-xhtml.js" integrity="sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE="></script> + </head> + <body> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt new file mode 100644 index 0000000..b0d4a300 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt
@@ -0,0 +1,5 @@ +CONSOLE ERROR: Failed to find a valid digest in the 'integrity' attribute for resource 'http://127.0.0.1:8000/security/subresourceIntegrity/resources/shared-with-xhtml.js' with computed SHA-256 integrity 'yM5ZyzNsyKfaXRY78zSGapeQKtl0oGdpPpYxgwl8XW8='. The resource has been blocked. +ALERT: FAIL +This test passes if only one 'FAIL' alert appears. + +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/shared-with-xhtml.html b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/shared-with-xhtml.html new file mode 100644 index 0000000..46aab8d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/shared-with-xhtml.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<body> + <script> + if (window.testRunner) + testRunner.dumpAsText(); + </script> + <p> + This test passes if only one 'FAIL' alert appears. + </p> + <iframe src="resources/shared-with-xhtml.xhtml"></iframe> + <iframe src="resources/shared-with-xhtml.html"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png index 75b3fc74..018367d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png new file mode 100644 index 0000000..018367d --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png index 75b3fc74..018367d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/scrollbars/border-box-rect-clips-scrollbars-expected.png index fedb6411..cb4dce0 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/scrollbars/border-box-rect-clips-scrollbars-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/scrollbars/border-box-rect-clips-scrollbars-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png index 942a7e3..87fab43 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png index fedb6411..cb4dce0 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png index f909d13..8c07beda 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/mac/scrollbars/border-box-rect-clips-scrollbars-expected.png index 3f249aa..fa48bc9e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/scrollbars/border-box-rect-clips-scrollbars-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/scrollbars/border-box-rect-clips-scrollbars-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png new file mode 100644 index 0000000..8c07beda --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png index f909d13..8c07beda 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png index 57434748..e83464152 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png index 3f249aa..fa48bc9e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/rootlayerscrolls/scrollbars/border-box-rect-clips-scrollbars-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png index 8a697828fc..38f87c2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png new file mode 100644 index 0000000..38f87c2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png index 8a697828fc..38f87c2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLCanvasElement.html b/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLCanvasElement.html index 161df617..97bb275f 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLCanvasElement.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLCanvasElement.html
@@ -1,7 +1,11 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> <script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> <script src="resources/mock-textdetection.js"></script> @@ -9,36 +13,23 @@ function detectShapeForCanvas(createDetector, createCanvas, - mockReady, + mock, detectionResultTest) { return new Promise(function(resolve, reject) { var img = new Image(); img.onload = function() { + var canvas = createCanvas(); + canvas.getContext("2d").drawImage(img, 0, 0); - var canvas = createCanvas(); - canvas.getContext("2d").drawImage(img, 0, 0); - - var theMock = null; - mockReady() - .then(mock => { - theMock = mock; - var detector = createDetector(); - return detector; - }) - .catch(error => { - assert_unreached("Error creating Mock Detector: " + error); - }) - .then(detector => { - return detector.detect(canvas); - }) - .then(detectionResult => { - detectionResultTest(detectionResult, theMock); - resolve("Success"); - }) - .catch(error => { - assert_unreached("Error during detect(canvas): " + error); - }); - } + var detector = createDetector(); + detector.detect(canvas) + .then(detectionResult => { + detectionResultTest(detectionResult, mock); + resolve("Success"); + }, error => { + assert_unreached("Error during detect(canvas): " + error); + }); + }; img.src = "../media/content/greenbox.png"; }); @@ -46,12 +37,12 @@ var createTestForCanvasElement = function(createDetector, createCanvas, - mockReady, + mock, detectionResultTest) { promise_test(function() { return detectShapeForCanvas(createDetector, createCanvas, - mockReady, + mock, detectionResultTest) .then(function(result) { assert_equals(result, "Success", "Detect 'Success'"); @@ -87,42 +78,42 @@ "Face - detect(HTMLCanvasElement)", () => { return new FaceDetector(); }, () => { return document.createElement("canvas"); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, FaceDetectorDetectionResultTest ], [ "Face - detect(OffscreenCanvas)", () => { return new FaceDetector(); }, () => { return new OffscreenCanvas(300, 150); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, FaceDetectorDetectionResultTest ], [ "Barcode - detect(HTMLCanvasElement)", () => { return new BarcodeDetector(); }, () => { return document.createElement("canvas"); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, BarcodeDetectorDetectionResultTest ], [ "Barcode - detect(OffscreenCanvas)", () => { return new BarcodeDetector(); }, () => { return new OffscreenCanvas(300, 150); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, BarcodeDetectorDetectionResultTest ], [ "Text - detect(HTMLCanvasElement)", () => { return new TextDetector(); }, () => { return document.createElement("canvas"); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, TextDetectorDetectionResultTest ], [ "Text - detect(OffscreenCanvas)", () => { return new TextDetector(); }, () => { return new OffscreenCanvas(300, 150); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, TextDetectorDetectionResultTest ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLImageElement.html b/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLImageElement.html index 8dfa455..7822219 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLImageElement.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLImageElement.html
@@ -1,7 +1,11 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> <script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> <script src="resources/mock-textdetection.js"></script> @@ -10,32 +14,18 @@ </body> <script> -var createTestForImageElement = function(createDetector, mockReady, +var createTestForImageElement = function(createDetector, mock, detectionResultTest) { - async_test(function(t) { + promise_test(async function() { var img = document.getElementById("img"); - var theMock = null; - mockReady() - .then(mock => { - theMock = mock; - var detector = createDetector(); - return detector; - }) - .catch(error => { - assert_unreached("Error creating Mock Detector: " + error); - }) - .then(detector => { - return detector.detect(img); - }) - .then(detectionResult => { - detectionResultTest(detectionResult, theMock); - t.done(); - }) - .catch(error => { - assert_unreached("Error during detect(img): " + error); - }); - + var detector = createDetector(); + try { + var detectionResult = await detector.detect(img); + detectionResultTest(detectionResult, mock); + } catch(error) { + assert_unreached("Error during detect(img): " + error); + } }); }; @@ -69,19 +59,19 @@ [ "Face - detect(HTMLImageElement)", () => { return new FaceDetector(); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, FaceDetectorDetectionResultTest ], [ "Barcode - detect(HTMLImageElement)", () => { return new BarcodeDetector(); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, BarcodeDetectorDetectionResultTest ], [ "Text - detect(HTMLImageElement)", () => { return new TextDetector(); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, TextDetectorDetectionResultTest ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLVideoElement.html b/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLVideoElement.html index 82dee81..2261ac6 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLVideoElement.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-HTMLVideoElement.html
@@ -1,13 +1,17 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> <script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> <script src="resources/mock-textdetection.js"></script> <script> -var createTestForVideoElement = function(createDetector, mockReady, +var createTestForVideoElement = function(createDetector, mock, detectionResultTest) { async_test(function(t) { var video = document.createElement("video"); @@ -15,27 +19,15 @@ video.loop = true; video.autoplay = true; video.onerror = this.unreached_func("<video> error"); - video.onplay = this.step_func(function() { - var theMock = null; - mockReady() - .then(mock => { - theMock = mock; - var detector = createDetector(); - return detector; - }) - .catch(error => { - assert_unreached("Error creating Mock Detector: " + error); - }) - .then(detector => { - return detector.detect(video); - }) - .then(detectionResult => { - detectionResultTest(detectionResult, theMock); - t.done(); - }) - .catch(error => { - assert_unreached("Error during detect(video): " + error); - }); + video.onplay = this.step_func(async function() { + var detector = createDetector(); + try { + var detectionResult = await detector.detect(video); + detectionResultTest(detectionResult, mock); + t.done(); + } catch (error) { + assert_unreached("Error during detect(video): " + error); + } }); video.load(); @@ -69,19 +61,19 @@ [ "Face - detect(HTMLVideoElement)", () => { return new FaceDetector(); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, FaceDetectorDetectionResultTest ], [ "Barcode - detect(HTMLVideoElement)", () => { return new BarcodeDetector(); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, BarcodeDetectorDetectionResultTest ], [ "Text - detect(HTMLVideoElement)", () => { return new TextDetector(); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, TextDetectorDetectionResultTest ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-ImageBitmap.html b/third_party/WebKit/LayoutTests/shapedetection/detection-ImageBitmap.html index 6a568616..79494d8 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-ImageBitmap.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-ImageBitmap.html
@@ -1,47 +1,32 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> <script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> <script src="resources/mock-textdetection.js"></script> <script> -var createTestForImageBitmap = function(createDetector, mockReady, +var createTestForImageBitmap = function(createDetector, mock, detectionResultTest) { async_test(function(t) { var img = new Image(); - img.onload = function() { - var theImageBitmap = null; - var theMock = null; + img.onload = async function() { + var imageBitmap = await createImageBitmap(img); + var detector = createDetector(); - createImageBitmap(img) - .then(imageBitmap => { - theImageBitmap = imageBitmap; - return mockReady(); - }) - .catch(error => { - assert_unreached("createImageBitmap() error: " + error); - }) - .then(mock => { - theMock = mock; - var detector = createDetector(); - return detector; - }) - .catch(error => { - assert_unreached("Error creating Mock Detector: " + error); - }) - .then(detector => { - return detector.detect(theImageBitmap); - }) - .then(detectionResult => { - detectionResultTest(detectionResult, theMock); - t.done(); - }) - .catch(error => { - assert_unreached("Error during detect(img): " + error); - }); + try { + var detectionResult = await detector.detect(imageBitmap); + detectionResultTest(detectionResult, mock); + t.done(); + } catch (error) { + assert_unreached("Error during detect(img): " + error); + } } img.src = "../media/content/greenbox.png"; }); @@ -73,19 +58,19 @@ [ "Face - detect(ImageBitmap)", () => { return new FaceDetector(); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, FaceDetectorDetectionResultTest ], [ "Barcode - detect(ImageBitmap)", () => { return new BarcodeDetector(); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, BarcodeDetectorDetectionResultTest ], [ "Text - detect(ImageBitmap)", () => { return new TextDetector(); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, TextDetectorDetectionResultTest ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-ImageData.html b/third_party/WebKit/LayoutTests/shapedetection/detection-ImageData.html index 57a5630..78dad14 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-ImageData.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-ImageData.html
@@ -1,43 +1,35 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> <script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> <script src="resources/mock-textdetection.js"></script> <script> -var createTestForImageData = function(createDetector, mockReady, +var createTestForImageData = function(createDetector, mock, detectionResultTest) { - async_test(function(t) { + async_test(async function(t) { var img = new Image(); - img.onload = function() { + img.onload = async function() { var canvas = document.createElement("canvas");; canvas.getContext("2d").drawImage(img, 0, 0); - var theMock = null; - mockReady() - .then(mock => { - theMock = mock; - var detector = createDetector(); - return detector; - }) - .catch(error => { - assert_unreached("Error creating Mock Detector: " + error); - }) - .then(detector => { - return detector.detect(canvas.getContext("2d").getImageData( - 0, 0, canvas.width, canvas.height)); - }) - .then(detectionResult => { - detectionResultTest(detectionResult, theMock); - t.done(); - }) - .catch(error => { - assert_unreached("Error during detect(canvas): " + error); - }); + var detector = createDetector(); + try { + var detectionResult = await detector.detect(canvas.getContext("2d") + .getImageData(0, 0, canvas.width, canvas.height)); + detectionResultTest(detectionResult, mock); + t.done(); + } catch (error) { + assert_unreached("Error during detect(canvas): " + error); + } } img.src = "../media/content/greenbox.png"; @@ -70,19 +62,19 @@ [ "Face - detect(ImageData)", () => { return new FaceDetector(); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, FaceDetectorDetectionResultTest ], [ "Barcode - detect(ImageData)", () => { return new BarcodeDetector(); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, BarcodeDetectorDetectionResultTest ], [ "Text - detect(ImageData)", () => { return new TextDetector(); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, TextDetectorDetectionResultTest ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-on-worker.html b/third_party/WebKit/LayoutTests/shapedetection/detection-on-worker.html index 09438fd..0031ff2 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-on-worker.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-on-worker.html
@@ -1,51 +1,25 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> -<script src="resources/mock-barcodedetection.js"></script> -<script src="resources/mock-facedetection.js"></script> -<script src="resources/mock-textdetection.js"></script> <script> // ImageBitmap is of transferable type and can be sent to and tested on worker. -var createTestForImageBitmap = function(detectorType, mockReady, - resultSize) { +var createTestForImageBitmap = function(detectorType, resultSize) { async_test(function(t) { - var img = new Image(); + let img = new Image(); - img.onload = function() { - var theImageBitmap = null; - var theMock = null; - - createImageBitmap(img) - .then(imageBitmap => { - theImageBitmap = imageBitmap; - return mockReady(); - }) - .catch(error => { - assert_unreached("createImageBitmap() error: " + error); - }) - .then(mock => { - theMock = mock; - return new Worker("resources/worker.js"); - }) - .catch(error => { - assert_unreached("Error creating Mock: " + error); - }) - .then(worker => { - worker.postMessage({ - detectorType: detectorType, - bitmap: theImageBitmap, - expectedLength: resultSize - }, [theImageBitmap]); - worker.onmessage = function(e) { - if(e.data=="PASS") - t.done(); - } - }) - .catch(error => { - assert_unreached("Error creating detector: " + error); - }); + img.onload = async function() { + let theImageBitmap = await createImageBitmap(img); + let worker = new Worker("resources/worker.js"); + worker.postMessage({ + detectorType: detectorType, + bitmap: theImageBitmap, + expectedLength: resultSize + }, [theImageBitmap]); + worker.onmessage = function(e) { + if(e.data=="PASS") + t.done(); + } } img.src = "../media/content/greenbox.png"; }, detectorType + "Detector detect(ImageBitmap) on worker"); @@ -57,19 +31,16 @@ [ "Face", "Face", - () => { return mockFaceDetectionProviderReady; }, 3 // Number of faces ], [ "Barcode", "Barcode", - () => { return mockBarcodeDetectionReady; }, 2 // Number of barcodes ], [ "Text", "Text", - () => { return mockTextDetectionReady; }, 2 // Number of text blocks ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-options.html b/third_party/WebKit/LayoutTests/shapedetection/detection-options.html index fb12e70..fa0100d 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-options.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-options.html
@@ -1,37 +1,27 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> <script src="resources/mock-facedetection.js"></script> <body> <img id="img" src="../media/content/greenbox.png"/> </body> <script> -async_test(function(t) { +promise_test(async function() { var img = document.getElementById("img"); - var theMock = null; - mockFaceDetectionProviderReady - .then(mock => { - theMock = mock; - return new FaceDetector(); - }) - .catch(error => { - assert_unreached("Error creating MockShapeDetection: " + error); - }) - .then(detectorWithDefault => detectorWithDefault.detect(img)) - .then(t.step_func(faceDetectionResult => { - assert_equals(theMock.getMaxDetectedFaces(), 10, "default maxDetectedFaces"); - assert_equals(theMock.getFastMode(), false, "default maxDetectedFaces"); - return new FaceDetector({maxDetectedFaces: 7, fastMode: true}); - })) - .then(detectorWithOptions => detectorWithOptions.detect(img)) - .then(t.step_func(faceDetectionResult => { - assert_equals(theMock.getMaxDetectedFaces(), 7, "maxDetectedFaces"); - assert_equals(theMock.getFastMode(), true, "maxDetectedFaces"); - t.done(); - })) - .catch(error => { - assert_unreached("Error creating detectors: " + error); - }); + var mock = mockFaceDetectionProvider; + + var detectorWithDefault = new FaceDetector(); + var faceDetectionResult = await detectorWithDefault.detect(img); + assert_equals(mock.getMaxDetectedFaces(), 10, "default maxDetectedFaces"); + assert_equals(mock.getFastMode(), false, "default maxDetectedFaces"); + + var detectorWithOptions = + new FaceDetector({maxDetectedFaces: 7, fastMode: true}); + faceDetectionResult = await detectorWithOptions.detect(img); + assert_equals(mock.getMaxDetectedFaces(), 7, "maxDetectedFaces"); + assert_equals(mock.getFastMode(), true, "maxDetectedFaces"); }, "Test that FaceDetectionOptions are correctly propagated"); </script>
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detection-security-test.html b/third_party/WebKit/LayoutTests/shapedetection/detection-security-test.html index 5f5f8de5..ffcaad04 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detection-security-test.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detection-security-test.html
@@ -1,29 +1,28 @@ <!DOCTYPE html> <script src=../resources/testharness.js></script> <script src=../resources/testharnessreport.js></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> +<script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> +<script src="resources/mock-textdetection.js"></script> <script> // Returns a Promise that is resolve()d if detect() is rejected. Needs an input // |element| (e.g. an HTMLImageElement or HTMLVideoElement) and a |url| to load. function detectOnElementAndExpectError(createDetector, element, url) { return new Promise(function(resolve, reject) { - var tryDetection = function() { - var theMock = null; - mockFaceDetectionProviderReady - .then(mock => { - return createDetector(); - }) - .then(detector => { - return detector.detect(element); - }) - .then(detectionResult => { - reject("Promise should have been rejected."); - }) - .catch(error => { - resolve(error); - }); + var tryDetection = async function() { + var detector = createDetector(); + try { + var detectionResult = await detector.detect(element); + reject("Promise should have been rejected."); + } catch (error) { + resolve(error); + } }; element.onload = tryDetection; element.onerror = tryDetection;
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html b/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html index 1df6e3f..3fafbb01 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html +++ b/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html
@@ -1,43 +1,35 @@ <!DOCTYPE html> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> -<script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"></script> +<script src="file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"></script> <script src="resources/mock-barcodedetection.js"></script> <script src="resources/mock-facedetection.js"></script> <script src="resources/mock-textdetection.js"></script> <script> -var createTestForImageData = function(createDetector, mockReady, +var createTestForImageData = function(createDetector, mock, detectionResultTest) { async_test(function(t) { var img = new Image(); - img.onload = function() { + img.onload = async function() { var canvas = document.createElement("canvas");; canvas.getContext("2d").drawImage(img, 0, 0); - var theMock = null; - mockReady() - .then(mock => { - theMock = mock; - var detector = createDetector(); - return detector; - }) - .catch(error => { - assert_unreached("Error creating Mock Detector: " + error); - }) - .then(detector => { - return detector.detect(canvas.getContext("2d").getImageData( - 0, 0, canvas.width, canvas.height)); - }) - .then(detectionResult => { - detectionResultTest(detectionResult); - t.done(); - }) - .catch(error => { - assert_unreached("Error during detect(canvas): " + error); - }); + var detector = createDetector(); + try { + var detectionResult = await detector.detect(canvas.getContext("2d") + .getImageData(0, 0, canvas.width, canvas.height)); + detectionResultTest(detectionResult); + t.done(); + } catch(error) { + assert_unreached("Error during detect(canvas): " + error); + } } img.src = "../media/content/greenbox.png"; @@ -69,19 +61,19 @@ [ "Face - detect(ImageData), [SameObject]", () => { return new FaceDetector(); }, - () => { return mockFaceDetectionProviderReady; }, + mockFaceDetectionProvider, CheckDetectedFaceSameObjects ], [ "Barcode - detect(ImageData), [SameObject]", () => { return new BarcodeDetector(); }, - () => { return mockBarcodeDetectionReady; }, + mockBarcodeDetection, CheckDetectedBarcodesSameObjects ], [ "Text - detect(ImageData), [SameObject]", () => { return new TextDetector(); }, - () => { return mockTextDetectionReady; }, + mockTextDetection, CheckDetectedTextBlocksSameObjects ] ]);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js index 4f9dd625a..de58094 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js
@@ -1,59 +1,49 @@ "use strict"; -let mockBarcodeDetectionReady = define( - 'mockBarcodeDetection', - ['services/shape_detection/public/interfaces/barcodedetection.mojom', - 'mojo/public/js/bindings', - 'mojo/public/js/core', - 'content/public/renderer/frame_interfaces', - 'content/public/renderer/interfaces', - ], (barcodeDetection, bindings, mojo, frameInterfaces, processInterfaces) => { +class MockBarcodeDetection { + constructor() { + this.bindingSet_ = new mojo.BindingSet( + shapeDetection.mojom.BarcodeDetection); - class MockBarcodeDetection { - constructor() { - this.bindingSet_ = new bindings.BindingSet( - barcodeDetection.BarcodeDetection); - - frameInterfaces.addInterfaceOverrideForTesting( - barcodeDetection.BarcodeDetection.name, - handle => this.bindingSet_.addBinding(this, handle)); - processInterfaces.addInterfaceOverrideForTesting( - barcodeDetection.BarcodeDetection.name, - handle => this.bindingSet_.addBinding(this, handle)); - } - - detect(bitmap_data) { - let receivedStruct = new Uint8Array(bitmap_data.pixel_data); - this.buffer_data_ = new Uint32Array(receivedStruct.buffer); - return Promise.resolve({ - results: [ - { - raw_value : "cats", - bounding_box: { x: 1.0, y: 1.0, width: 100.0, height: 100.0 }, - corner_points: [ - { x: 1.0, y: 1.0 }, - { x: 101.0, y: 1.0 }, - { x: 101.0, y: 101.0 }, - { x: 1.0, y: 101.0 } - ], - }, - { - raw_value : "dogs", - bounding_box: { x: 2.0, y: 2.0, width: 50.0, height: 50.0 }, - corner_points: [ - { x: 2.0, y: 2.0 }, - { x: 52.0, y: 2.0 }, - { x: 52.0, y: 52.0 }, - { x: 2.0, y: 52.0 } - ], - }, - ], - }); - } - - getFrameData() { - return this.buffer_data_; - } + this.interceptor_ = new MojoInterfaceInterceptor( + shapeDetection.mojom.BarcodeDetection.name); + this.interceptor_.oninterfacerequest = + e => this.bindingSet_.addBinding(this, e.handle); + this.interceptor_.start(); } - return new MockBarcodeDetection(); -}); + + detect(bitmap_data) { + let receivedStruct = new Uint8Array(bitmap_data.pixel_data); + this.buffer_data_ = new Uint32Array(receivedStruct.buffer); + return Promise.resolve({ + results: [ + { + rawValue : "cats", + boundingBox: { x: 1.0, y: 1.0, width: 100.0, height: 100.0 }, + cornerPoints: [ + { x: 1.0, y: 1.0 }, + { x: 101.0, y: 1.0 }, + { x: 101.0, y: 101.0 }, + { x: 1.0, y: 101.0 } + ], + }, + { + rawValue : "dogs", + boundingBox: { x: 2.0, y: 2.0, width: 50.0, height: 50.0 }, + cornerPoints: [ + { x: 2.0, y: 2.0 }, + { x: 52.0, y: 2.0 }, + { x: 52.0, y: 52.0 }, + { x: 2.0, y: 52.0 } + ], + }, + ], + }); + } + + getFrameData() { + return this.buffer_data_; + } +} + +let mockBarcodeDetection = new MockBarcodeDetection();
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js index e587cbf..f5c53e0 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js
@@ -1,77 +1,65 @@ "use strict"; -let mockFaceDetectionProviderReady = define( - 'mockFaceDetectionProvider', - ['services/shape_detection/public/interfaces/facedetection.mojom', - 'services/shape_detection/public/interfaces/facedetection_provider.mojom', - 'mojo/public/js/bindings', - 'mojo/public/js/core', - 'content/public/renderer/frame_interfaces', - 'content/public/renderer/interfaces', - ], (faceDetection, faceDetectionProvider, bindings, mojo, frameInterfaces, - processInterfaces) => { +class MockFaceDetectionProvider { + constructor() { + this.bindingSet_ = new mojo.BindingSet( + shapeDetection.mojom.FaceDetectionProvider); - class MockFaceDetectionProvider { - constructor() { - this.bindingSet_ = new bindings.BindingSet( - faceDetectionProvider.FaceDetectionProvider); - - frameInterfaces.addInterfaceOverrideForTesting( - faceDetectionProvider.FaceDetectionProvider.name, - handle => this.bindingSet_.addBinding(this, handle)); - processInterfaces.addInterfaceOverrideForTesting( - faceDetectionProvider.FaceDetectionProvider.name, - handle => this.bindingSet_.addBinding(this, handle)); - } - - createFaceDetection(request, options) { - this.mockService_ = new MockFaceDetection(request, options); - } - - getFrameData() { - return this.mockService_.bufferData_; - } - - getMaxDetectedFaces() { - return this.mockService_.maxDetectedFaces_; - } - - getFastMode () { - return this.mockService_.fastMode_; - } + this.interceptor_ = new MojoInterfaceInterceptor( + shapeDetection.mojom.FaceDetectionProvider.name); + this.interceptor_.oninterfacerequest = + e => this.bindingSet_.addBinding(this, e.handle); + this.interceptor_.start(); } - class MockFaceDetection { - constructor(request, options) { - this.maxDetectedFaces_ = options.max_detected_faces; - this.fastMode_ = options.fast_mode; - this.binding_ = new bindings.Binding(faceDetection.FaceDetection, this, - request); - } - - detect(bitmap_data) { - let receivedStruct = new Uint8Array(bitmap_data.pixel_data); - this.bufferData_ = new Uint32Array(receivedStruct.buffer); - return Promise.resolve({ - results: [ - { - bounding_box: {x: 1.0, y: 1.0, width: 100.0, height: 100.0}, - landmarks: [{ - type: faceDetection.LandmarkType.EYE, - location: {x: 4.0, y: 5.0} - }] - }, - { - bounding_box: {x: 2.0, y: 2.0, width: 200.0, height: 200.0}, - landmarks: [] - }, - { - bounding_box: {x: 3.0, y: 3.0, width: 300.0, height: 300.0}, - landmarks: [] - }, - ] - }); - } + createFaceDetection(request, options) { + this.mockService_ = new MockFaceDetection(request, options); } - return new MockFaceDetectionProvider(); -}); + + getFrameData() { + return this.mockService_.bufferData_; + } + + getMaxDetectedFaces() { + return this.mockService_.maxDetectedFaces_; + } + + getFastMode () { + return this.mockService_.fastMode_; + } +} + +class MockFaceDetection { + constructor(request, options) { + this.maxDetectedFaces_ = options.maxDetectedFaces; + this.fastMode_ = options.fastMode; + this.binding_ = + new mojo.Binding(shapeDetection.mojom.FaceDetection, this, request); + } + + detect(bitmap_data) { + let receivedStruct = new Uint8Array(bitmap_data.pixelData); + this.bufferData_ = new Uint32Array(receivedStruct.buffer); + return Promise.resolve({ + results: [ + { + boundingBox: {x: 1.0, y: 1.0, width: 100.0, height: 100.0}, + landmarks: [{ + type: shapeDetection.mojom.LandmarkType.EYE, + location: {x: 4.0, y: 5.0} + }] + }, + { + boundingBox: {x: 2.0, y: 2.0, width: 200.0, height: 200.0}, + landmarks: [] + }, + { + boundingBox: {x: 3.0, y: 3.0, width: 300.0, height: 300.0}, + landmarks: [] + }, + ] + }); + } +} + +let mockFaceDetectionProvider = new MockFaceDetectionProvider();
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js index a92054e..7e7c394 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js
@@ -1,46 +1,37 @@ "use strict"; -let mockTextDetectionReady = define( - 'mockTextDetection', - ['services/shape_detection/public/interfaces/textdetection.mojom', - 'mojo/public/js/bindings', - 'mojo/public/js/core', - 'content/public/renderer/frame_interfaces', - 'content/public/renderer/interfaces', - ], (textDetection, bindings, mojo, frameInterfaces, processInterfaces) => { +class MockTextDetection { + constructor() { + this.bindingSet_ = + new mojo.BindingSet(shapeDetection.mojom.TextDetection); - class MockTextDetection { - constructor() { - this.bindingSet_ = new bindings.BindingSet(textDetection.TextDetection); - - frameInterfaces.addInterfaceOverrideForTesting( - textDetection.TextDetection.name, - handle => this.bindingSet_.addBinding(this, handle)); - processInterfaces.addInterfaceOverrideForTesting( - textDetection.TextDetection.name, - handle => this.bindingSet_.addBinding(this, handle)); - } - - detect(bitmap_data) { - let receivedStruct = new Uint8Array(bitmap_data.pixel_data); - this.buffer_data_ = new Uint32Array(receivedStruct.buffer); - return Promise.resolve({ - results: [ - { - raw_value : "cats", - bounding_box: { x: 1.0, y: 1.0, width: 100.0, height: 100.0 } - }, - { - raw_value : "dogs", - bounding_box: { x: 2.0, y: 2.0, width: 50.0, height: 50.0 } - }, - ], - }); - } - - getFrameData() { - return this.buffer_data_; - } + this.interceptor_ = new MojoInterfaceInterceptor( + shapeDetection.mojom.TextDetection.name); + this.interceptor_.oninterfacerequest = + e => this.bindingSet_.addBinding(this, e.handle); + this.interceptor_.start(); } - return new MockTextDetection(); -}); + + detect(bitmap_data) { + let receivedStruct = new Uint8Array(bitmap_data.pixel_data); + this.buffer_data_ = new Uint32Array(receivedStruct.buffer); + return Promise.resolve({ + results: [ + { + rawValue : "cats", + boundingBox: { x: 1.0, y: 1.0, width: 100.0, height: 100.0 } + }, + { + rawValue : "dogs", + boundingBox: { x: 2.0, y: 2.0, width: 50.0, height: 50.0 } + }, + ], + }); + } + + getFrameData() { + return this.buffer_data_; + } +} + +let mockTextDetection = new MockTextDetection();
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/worker.js b/third_party/WebKit/LayoutTests/shapedetection/resources/worker.js index c26b28b..a590a500 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/worker.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/worker.js
@@ -1,21 +1,30 @@ importScripts("../../resources/testharness.js"); +importScripts("file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"); +importScripts("file:///gen/skia/public/interfaces/bitmap.mojom.js"); +importScripts("file:///gen/ui/gfx/geometry/mojo/geometry.mojom.js"); +importScripts("file:///gen/services/shape_detection/public/interfaces/barcodedetection.mojom.js"); +importScripts("file:///gen/services/shape_detection/public/interfaces/facedetection.mojom.js"); +importScripts("file:///gen/services/shape_detection/public/interfaces/facedetection_provider.mojom.js"); +importScripts("file:///gen/services/shape_detection/public/interfaces/textdetection.mojom.js"); +importScripts("mock-barcodedetection.js"); +importScripts("mock-facedetection.js"); +importScripts("mock-textdetection.js"); -onmessage = function(e) { - var detector; +onmessage = async function(e) { + let detector; switch (e.data.detectorType) { case "Face": detector = new FaceDetector(); break; case "Barcode": detector = new BarcodeDetector(); break; case "Text": detector = new TextDetector(); break; } - var imageBitmap = e.data.bitmap; - detector.detect(imageBitmap) - .then(detectionResult => { - assert_equals(detectionResult.length, e.data.expectedLength, - "Number of " + e.data.detectorType); - postMessage("PASS"); - }) - .catch(error => { - assert_unreached("Error during detect(img): " + error); - }); + let imageBitmap = e.data.bitmap; + try { + let detectionResult = await detector.detect(imageBitmap); + assert_equals(detectionResult.length, e.data.expectedLength, + "Number of " + e.data.detectorType); + postMessage("PASS"); + } catch (error) { + assert_unreached("Error during detect(img): " + error); + } }
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt index 260dc1d..9aa28ab3 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -24,21 +24,26 @@ getter colCount getter colIndex getter colSpan + getter controls getter current + getter describedBy getter details getter disabled getter errorMessage getter expanded + getter flowTo getter hidden getter invalid getter keyShortcuts getter label + getter labeledBy getter level getter live getter modal getter multiline getter multiselectable getter orientation + getter owns getter placeholder getter posInSet getter pressed @@ -66,21 +71,26 @@ setter colCount setter colIndex setter colSpan + setter controls setter current + setter describedBy setter details setter disabled setter errorMessage setter expanded + setter flowTo setter hidden setter invalid setter keyShortcuts setter label + setter labeledBy setter level setter live setter modal setter multiline setter multiselectable setter orientation + setter owns setter placeholder setter posInSet setter pressed @@ -99,6 +109,15 @@ setter valueMin setter valueNow setter valueText +interface AccessibleNodeList + attribute @@toStringTag + getter length + method @@iterator + method add + method constructor + method item + method remove + setter length interface AmbientLightSensor : Sensor attribute @@toStringTag getter illuminance
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 8563df7a..84197b0 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -24,21 +24,26 @@ getter colCount getter colIndex getter colSpan + getter controls getter current + getter describedBy getter details getter disabled getter errorMessage getter expanded + getter flowTo getter hidden getter invalid getter keyShortcuts getter label + getter labeledBy getter level getter live getter modal getter multiline getter multiselectable getter orientation + getter owns getter placeholder getter posInSet getter pressed @@ -66,21 +71,26 @@ setter colCount setter colIndex setter colSpan + setter controls setter current + setter describedBy setter details setter disabled setter errorMessage setter expanded + setter flowTo setter hidden setter invalid setter keyShortcuts setter label + setter labeledBy setter level setter live setter modal setter multiline setter multiselectable setter orientation + setter owns setter placeholder setter posInSet setter pressed @@ -99,6 +109,15 @@ setter valueMin setter valueNow setter valueText +interface AccessibleNodeList + attribute @@toStringTag + getter length + method @@iterator + method add + method constructor + method item + method remove + setter length interface AmbientLightSensor : Sensor attribute @@toStringTag getter illuminance
diff --git a/third_party/WebKit/Source/bindings/core/v8/ActivityLoggerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ActivityLoggerTest.cpp index ef367bc6..bcb39ae 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ActivityLoggerTest.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ActivityLoggerTest.cpp
@@ -70,7 +70,7 @@ Vector<String> logged_activities_; }; -class ActivityLoggerTest : public testing::Test { +class ActivityLoggerTest : public ::testing::Test { protected: ActivityLoggerTest() { activity_logger_ = new TestActivityLogger();
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp index a8176cd..55c122b 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
@@ -34,7 +34,8 @@ ->CurrentThread() ->Scheduler() ->LoadingTaskRunner()), - settings_(Settings::Create()) { + settings_(Settings::Create()), + dummy_document_(Document::Create()) { resource_ = ScriptResource::CreateForTest( KURL(kParsedURLString, "http://www.streaming-test.com/"), UTF8Encoding()); @@ -45,6 +46,8 @@ // the method(s) to return default values. EXPECT_CALL(*element, IntegrityAttributeValue()) .WillRepeatedly(::testing::Return(String())); + EXPECT_CALL(*element, GetDocument()) + .WillRepeatedly(::testing::ReturnRef(*dummy_document_.Get())); pending_script_ = ClassicPendingScript::Create(element, resource_.Get()); ScriptStreamer::SetSmallScriptThresholdForTesting(0); @@ -100,6 +103,8 @@ // ScriptResource::appendData. Persistent<ScriptResource> resource_; Persistent<ClassicPendingScript> pending_script_; + + Persistent<Document> dummy_document_; }; class TestPendingScriptClient final
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp index 90042c7..2a2da6b 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -49,8 +49,6 @@ #include "platform/wtf/text/StringBuilder.h" #include "platform/wtf/text/StringConcatenate.h" -using namespace WTF; - namespace blink { // Check for a CSS prefix. @@ -161,7 +159,7 @@ property_names.push_back(getJSPropertyName(property_id)); } std::sort(property_names.begin(), property_names.end(), - CodePointCompareLessThan); + WTF::CodePointCompareLessThan); property_names_length = property_names.size(); }
diff --git a/third_party/WebKit/Source/build/scripts/make_css_property_names.py b/third_party/WebKit/Source/build/scripts/make_css_property_names.py index f560950d..b239019 100755 --- a/third_party/WebKit/Source/build/scripts/make_css_property_names.py +++ b/third_party/WebKit/Source/build/scripts/make_css_property_names.py
@@ -250,6 +250,7 @@ gperf_args = [self.gperf_path, '--key-positions=*', '-P', '-n'] gperf_args.extend(['-m', '50']) # Pick best of 50 attempts. gperf_args.append('-D') # Allow duplicate hashes -> More compact code. + gperf_args.extend(['-Q', 'CSSPropStringPool']) # Unique var names. # If gperf isn't in the path we get an OSError. We don't want to use # the normal solution of shell=True (as this has to run on many
diff --git a/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py b/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py index f8b773c..cc51f2d 100755 --- a/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py +++ b/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py
@@ -174,6 +174,7 @@ gperf_args = [self.gperf_path, '--key-positions=*', '-P', '-n'] gperf_args.extend(['-m', '50']) # Pick best of 50 attempts. gperf_args.append('-D') # Allow duplicate hashes -> More compact code. + gperf_args.extend(['-Q', 'CSSValueStringPool']) # Unique var names. # If gperf isn't in the path we get an OSError. We don't want to use # the normal solution of shell=True (as this has to run on many
diff --git a/third_party/WebKit/Source/build/scripts/templates/ElementFactory.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/ElementFactory.cpp.tmpl index 8327d67..b7b4be5b 100644 --- a/third_party/WebKit/Source/build/scripts/templates/ElementFactory.cpp.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/ElementFactory.cpp.tmpl
@@ -22,26 +22,24 @@ namespace blink { -using namespace {{namespace}}Names; - -typedef {{namespace}}Element* (*ConstructorFunction)( +typedef {{namespace}}Element* (*{{namespace}}ConstructorFunction)( Document&, CreateElementFlags); -typedef HashMap<AtomicString, ConstructorFunction> FunctionMap; +typedef HashMap<AtomicString, {{namespace}}ConstructorFunction> {{namespace}}FunctionMap; -static FunctionMap* g_constructors = 0; +static {{namespace}}FunctionMap* g_{{namespace}}_constructors = 0; {% for tag in tags|sort if not tag.noConstructor %} -static {{namespace}}Element* {{tag|symbol}}Constructor( +static {{namespace}}Element* {{namespace}}{{tag|symbol}}Constructor( Document& document, CreateElementFlags flags) { {% if tag.runtimeEnabled %} if (!RuntimeEnabledFeatures::{{tag.runtimeEnabled}}Enabled()) - return {{fallback_interface}}::Create({{tag|symbol}}Tag, document); + return {{fallback_interface}}::Create({{namespace}}Names::{{tag|symbol}}Tag, document); {% endif %} return {{tag.interface}}::Create( - {%- if tag.multipleTagNames %}{{tag|symbol}}Tag, {% endif -%} + {%- if tag.multipleTagNames %}{{namespace}}Names::{{tag|symbol}}Tag, {% endif -%} document {%- if tag.constructorNeedsCreatedByParser %}, flags & kCreatedByParser{% endif -%} ); @@ -50,30 +48,30 @@ struct Create{{namespace}}FunctionMapData { const QualifiedName& tag; - ConstructorFunction func; + {{namespace}}ConstructorFunction func; }; static void create{{namespace}}FunctionMap() { - DCHECK(!g_constructors); - g_constructors = new FunctionMap; + DCHECK(!g_{{namespace}}_constructors); + g_{{namespace}}_constructors = new {{namespace}}FunctionMap; // Empty array initializer lists are illegal [dcl.init.aggr] and will not // compile in MSVC. If tags list is empty, add check to skip this. static const Create{{namespace}}FunctionMapData data[] = { {% for tag in tags|sort if not tag.noConstructor %} - { {{tag|symbol}}Tag, {{tag|symbol}}Constructor }, + { {{namespace}}Names::{{tag|symbol}}Tag, {{namespace}}{{tag|symbol}}Constructor }, {% endfor %} }; for (size_t i = 0; i < WTF_ARRAY_LENGTH(data); i++) - g_constructors->Set(data[i].tag.LocalName(), data[i].func); + g_{{namespace}}_constructors->Set(data[i].tag.LocalName(), data[i].func); } {{namespace}}Element* {{namespace}}ElementFactory::create{{namespace}}Element( const AtomicString& localName, Document& document, CreateElementFlags flags) { - if (!g_constructors) + if (!g_{{namespace}}_constructors) create{{namespace}}FunctionMap(); - if (ConstructorFunction function = g_constructors->at(localName)) + if ({{namespace}}ConstructorFunction function = g_{{namespace}}_constructors->at(localName)) return function(document, flags); {% if namespace == 'HTML' %} @@ -93,12 +91,12 @@ if (document.RegistrationContext() && V0CustomElement::IsValidName(localName)) { Element* element = document.RegistrationContext()->CreateCustomTagElement( - document, QualifiedName(g_null_atom, localName, {{namespace_prefix}}NamespaceURI)); + document, QualifiedName(g_null_atom, localName, {{namespace}}Names::{{namespace_prefix}}NamespaceURI)); SECURITY_DCHECK(element->Is{{namespace}}Element()); return To{{namespace}}Element(element); } - return {{fallback_interface}}::Create(QualifiedName(g_null_atom, localName, {{namespace_prefix}}NamespaceURI), document); + return {{fallback_interface}}::Create(QualifiedName(g_null_atom, localName, {{namespace}}Names::{{namespace_prefix}}NamespaceURI), document); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index ecf084c..c8c5ae7 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -84,6 +84,7 @@ "css/cssom/StylePropertyMap.idl", "css/cssom/StylePropertyMapReadonly.idl", "dom/AccessibleNode.idl", + "dom/AccessibleNodeList.idl", "dom/ArrayBuffer.idl", "dom/ArrayBufferView.idl", "dom/Attr.idl",
diff --git a/third_party/WebKit/Source/core/css/FontFace.idl b/third_party/WebKit/Source/core/css/FontFace.idl index 8d94ec59..ea9368e 100644 --- a/third_party/WebKit/Source/core/css/FontFace.idl +++ b/third_party/WebKit/Source/core/css/FontFace.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://dev.w3.org/csswg/css-font-loading/#fontface-interface +// https://drafts.csswg.org/css-font-loading/#fontface-interface enum FontFaceLoadStatus { "unloaded",
diff --git a/third_party/WebKit/Source/core/css/FontFaceDescriptors.idl b/third_party/WebKit/Source/core/css/FontFaceDescriptors.idl index 5330445..fa21377 100644 --- a/third_party/WebKit/Source/core/css/FontFaceDescriptors.idl +++ b/third_party/WebKit/Source/core/css/FontFaceDescriptors.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/csswg/css-font-loading/#dictdef-fontfacedescriptors +// https://drafts.csswg.org/css-font-loading/#dictdef-fontfacedescriptors dictionary FontFaceDescriptors { DOMString style = "normal";
diff --git a/third_party/WebKit/Source/core/css/FontFaceSet.idl b/third_party/WebKit/Source/core/css/FontFaceSet.idl index f636dada..2e8622d 100644 --- a/third_party/WebKit/Source/core/css/FontFaceSet.idl +++ b/third_party/WebKit/Source/core/css/FontFaceSet.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://dev.w3.org/csswg/css-font-loading/#FontFaceSet-interface +// https://drafts.csswg.org/css-font-loading/#FontFaceSet-interface enum FontFaceSetLoadStatus { "loading", "loaded" };
diff --git a/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl b/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl index f22dd2c..59da6a5 100644 --- a/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl +++ b/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://dev.w3.org/csswg/css-font-loading/#fontfacesetloadevent +// https://drafts.csswg.org/css-font-loading/#fontfacesetloadevent [ Constructor(DOMString type, optional FontFaceSetLoadEventInit eventInitDict),
diff --git a/third_party/WebKit/Source/core/css/FontFaceSetLoadEventInit.idl b/third_party/WebKit/Source/core/css/FontFaceSetLoadEventInit.idl index 288c8005..e47188d 100644 --- a/third_party/WebKit/Source/core/css/FontFaceSetLoadEventInit.idl +++ b/third_party/WebKit/Source/core/css/FontFaceSetLoadEventInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/csswg/css-font-loading/#fontfacesetloadevent +// https://drafts.csswg.org/css-font-loading/#fontfacesetloadevent dictionary FontFaceSetLoadEventInit : EventInit { sequence<FontFace> fontfaces = [];
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp index 05f23c0..18a4673 100644 --- a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp +++ b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
@@ -5,6 +5,7 @@ #include "core/dom/AccessibleNode.h" #include "core/dom/AXObjectCache.h" +#include "core/dom/AccessibleNodeList.h" #include "core/dom/Element.h" #include "core/dom/QualifiedName.h" #include "core/frame/Settings.h" @@ -70,6 +71,31 @@ return g_null_name; } +QualifiedName GetCorrespondingARIAAttribute(AOMRelationListProperty property) { + switch (property) { + case AOMRelationListProperty::kDescribedBy: + return aria_describedbyAttr; + break; + case AOMRelationListProperty::kControls: + return aria_controlsAttr; + break; + case AOMRelationListProperty::kFlowTo: + return aria_flowtoAttr; + break; + case AOMRelationListProperty::kLabeledBy: + // Note that there are two allowed spellings of this attribute. + // Callers should check both. + return aria_labelledbyAttr; + break; + case AOMRelationListProperty::kOwns: + return aria_ownsAttr; + break; + } + + NOTREACHED(); + return g_null_name; +} + QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) { switch (property) { case AOMBooleanProperty::kAtomic: @@ -212,6 +238,43 @@ return nullptr; } +// static +AccessibleNodeList* AccessibleNode::GetProperty( + Element* element, + AOMRelationListProperty property) { + if (!element) + return nullptr; + + if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) { + for (const auto& item : accessible_node->relation_list_properties_) { + if (item.first == property && item.second) + return item.second; + } + } + + return nullptr; +} + +// static +bool AccessibleNode::GetProperty(Element* element, + AOMRelationListProperty property, + HeapVector<Member<Element>>& targets) { + AccessibleNodeList* node_list = GetProperty(element, property); + if (!node_list) + return false; + + for (size_t i = 0; i < node_list->length(); ++i) { + AccessibleNode* accessible_node = node_list->item(i); + if (accessible_node) { + Element* element = accessible_node->element(); + if (element) + targets.push_back(element); + } + } + + return true; +} + template <typename P, typename T> static T FindPropertyValue(P property, bool& is_null, @@ -324,6 +387,39 @@ } // static +bool AccessibleNode::GetPropertyOrARIAAttribute( + Element* element, + AOMRelationListProperty property, + HeapVector<Member<Element>>& targets) { + if (!element) + return false; + + if (GetProperty(element, property, targets)) + return true; + + // Fall back on the equivalent ARIA attribute. + QualifiedName attribute = GetCorrespondingARIAAttribute(property); + String value = element->FastGetAttribute(attribute).GetString(); + if (value.IsEmpty() && property == AOMRelationListProperty::kLabeledBy) + value = element->FastGetAttribute(aria_labeledbyAttr).GetString(); + if (value.IsEmpty()) + return false; + + value.SimplifyWhiteSpace(); + Vector<String> ids; + value.Split(' ', ids); + if (ids.IsEmpty()) + return false; + + TreeScope& scope = element->GetTreeScope(); + for (const auto& id : ids) { + if (Element* id_element = scope.getElementById(AtomicString(id))) + targets.push_back(id_element); + } + return true; +} + +// static bool AccessibleNode::GetPropertyOrARIAAttribute(Element* element, AOMBooleanProperty property, bool& is_null) { @@ -429,9 +525,17 @@ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first)); } for (auto& item : accessible_node->relation_properties_) { + if (!item.second) + continue; client->AddRelationProperty(item.first, *item.second); shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first)); } + for (auto& item : accessible_node->relation_list_properties_) { + if (!item.second) + continue; + client->AddRelationListProperty(item.first, *item.second); + shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first)); + } } AccessibleNode* AccessibleNode::activeDescendant() const { @@ -507,6 +611,15 @@ NotifyAttributeChanged(aria_colspanAttr); } +AccessibleNodeList* AccessibleNode::controls() const { + return GetProperty(element_, AOMRelationListProperty::kControls); +} + +void AccessibleNode::setControls(AccessibleNodeList* controls) { + SetRelationListProperty(AOMRelationListProperty::kControls, controls); + NotifyAttributeChanged(aria_controlsAttr); +} + AtomicString AccessibleNode::current() const { return GetProperty(element_, AOMStringProperty::kCurrent); } @@ -518,6 +631,15 @@ cache->HandleAttributeChanged(aria_currentAttr, element_); } +AccessibleNodeList* AccessibleNode::describedBy() { + return GetProperty(element_, AOMRelationListProperty::kDescribedBy); +} + +void AccessibleNode::setDescribedBy(AccessibleNodeList* described_by) { + SetRelationListProperty(AOMRelationListProperty::kDescribedBy, described_by); + NotifyAttributeChanged(aria_describedbyAttr); +} + AccessibleNode* AccessibleNode::details() const { return GetProperty(element_, AOMRelationProperty::kDetails); } @@ -554,6 +676,15 @@ NotifyAttributeChanged(aria_expandedAttr); } +AccessibleNodeList* AccessibleNode::flowTo() const { + return GetProperty(element_, AOMRelationListProperty::kFlowTo); +} + +void AccessibleNode::setFlowTo(AccessibleNodeList* flow_to) { + SetRelationListProperty(AOMRelationListProperty::kFlowTo, flow_to); + NotifyAttributeChanged(aria_flowtoAttr); +} + bool AccessibleNode::hidden(bool& is_null) const { return GetProperty(element_, AOMBooleanProperty::kHidden, is_null); } @@ -590,6 +721,15 @@ NotifyAttributeChanged(aria_labelAttr); } +AccessibleNodeList* AccessibleNode::labeledBy() { + return GetProperty(element_, AOMRelationListProperty::kLabeledBy); +} + +void AccessibleNode::setLabeledBy(AccessibleNodeList* labeled_by) { + SetRelationListProperty(AOMRelationListProperty::kLabeledBy, labeled_by); + NotifyAttributeChanged(aria_labelledbyAttr); +} + uint32_t AccessibleNode::level(bool& is_null) const { return GetProperty(element_, AOMUIntProperty::kLevel, is_null); } @@ -645,6 +785,15 @@ NotifyAttributeChanged(aria_orientationAttr); } +AccessibleNodeList* AccessibleNode::owns() const { + return GetProperty(element_, AOMRelationListProperty::kOwns); +} + +void AccessibleNode::setOwns(AccessibleNodeList* owns) { + SetRelationListProperty(AOMRelationListProperty::kOwns, owns); + NotifyAttributeChanged(aria_ownsAttr); +} + AtomicString AccessibleNode::placeholder() const { return GetProperty(element_, AOMStringProperty::kPlaceholder); } @@ -831,6 +980,22 @@ relation_properties_.push_back(std::make_pair(property, value)); } +void AccessibleNode::SetRelationListProperty(AOMRelationListProperty property, + AccessibleNodeList* value) { + for (auto& item : relation_list_properties_) { + if (item.first == property) { + if (item.second) + item.second->RemoveOwner(property, this); + if (value) + value->AddOwner(property, this); + item.second = value; + return; + } + } + + relation_list_properties_.push_back(std::make_pair(property, value)); +} + template <typename P, typename T> static void SetProperty(P property, T value, @@ -874,6 +1039,10 @@ SetProperty(property, value, is_null, float_properties_); } +void AccessibleNode::OnRelationListChanged(AOMRelationListProperty property) { + NotifyAttributeChanged(GetCorrespondingARIAAttribute(property)); +} + void AccessibleNode::NotifyAttributeChanged( const blink::QualifiedName& attribute) { // TODO(dmazzoni): Make a cleaner API for this rather than pretending @@ -889,6 +1058,7 @@ DEFINE_TRACE(AccessibleNode) { visitor->Trace(element_); visitor->Trace(relation_properties_); + visitor->Trace(relation_list_properties_); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.h b/third_party/WebKit/Source/core/dom/AccessibleNode.h index aacad2d3..d7362df 100644 --- a/third_party/WebKit/Source/core/dom/AccessibleNode.h +++ b/third_party/WebKit/Source/core/dom/AccessibleNode.h
@@ -15,6 +15,7 @@ namespace blink { +class AccessibleNodeList; class AXObjectCache; class Element; class QualifiedName; @@ -69,6 +70,14 @@ kErrorMessage, }; +enum class AOMRelationListProperty { + kDescribedBy, + kControls, + kFlowTo, + kLabeledBy, + kOwns, +}; + // All of the properties of AccessibleNode that have a signed integer type. // (These all allow the value -1.) enum class AOMIntProperty { kColCount, kRowCount, kSetSize }; @@ -87,6 +96,8 @@ virtual void AddFloatProperty(AOMFloatProperty, float) = 0; virtual void AddRelationProperty(AOMRelationProperty, const AccessibleNode&) = 0; + virtual void AddRelationListProperty(AOMRelationListProperty, + const AccessibleNodeList&) = 0; }; // Accessibility Object Model node @@ -110,6 +121,13 @@ // Returns the given relation property if the Element has an AccessibleNode. static AccessibleNode* GetProperty(Element*, AOMRelationProperty); + // Returns the given relation list property if the Element has an + // AccessibleNode. + static AccessibleNodeList* GetProperty(Element*, AOMRelationListProperty); + static bool GetProperty(Element*, + AOMRelationListProperty, + HeapVector<Member<Element>>&); + // Returns the value of the given property if the // Element has an AccessibleNode. Sets |isNull| if the property and // attribute are not present. @@ -129,6 +147,13 @@ static AccessibleNode* GetPropertyOrARIAAttribute(Element*, AOMRelationProperty); + // Returns true and provides the the value of the given relation + // list property if the Element has an AccessibleNode, or if it has + // the equivalent ARIA attribute. Otherwise returns false. + static bool GetPropertyOrARIAAttribute(Element*, + AOMRelationListProperty, + HeapVector<Member<Element>>&); + // Returns the value of the given property if the // Element has an AccessibleNode, otherwise returns the equivalent // ARIA attribute. Sets |isNull| if the property and attribute are not @@ -179,9 +204,15 @@ uint32_t colSpan(bool& is_null) const; void setColSpan(uint32_t, bool is_null); + AccessibleNodeList* controls() const; + void setControls(AccessibleNodeList*); + AtomicString current() const; void setCurrent(const AtomicString&); + AccessibleNodeList* describedBy(); + void setDescribedBy(AccessibleNodeList*); + AccessibleNode* details() const; void setDetails(AccessibleNode*); @@ -194,6 +225,9 @@ bool expanded(bool& is_null) const; void setExpanded(bool, bool is_null); + AccessibleNodeList* flowTo() const; + void setFlowTo(AccessibleNodeList*); + bool hidden(bool& is_null) const; void setHidden(bool, bool is_null); @@ -206,6 +240,9 @@ AtomicString label() const; void setLabel(const AtomicString&); + AccessibleNodeList* labeledBy(); + void setLabeledBy(AccessibleNodeList*); + uint32_t level(bool& is_null) const; void setLevel(uint32_t, bool is_null); @@ -224,6 +261,9 @@ AtomicString orientation() const; void setOrientation(const AtomicString&); + AccessibleNodeList* owns() const; + void setOwns(AccessibleNodeList*); + AtomicString placeholder() const; void setPlaceholder(const AtomicString&); @@ -280,9 +320,14 @@ DECLARE_VIRTUAL_TRACE(); + protected: + friend class AccessibleNodeList; + void OnRelationListChanged(AOMRelationListProperty); + private: void SetStringProperty(AOMStringProperty, const AtomicString&); void SetRelationProperty(AOMRelationProperty, AccessibleNode*); + void SetRelationListProperty(AOMRelationListProperty, AccessibleNodeList*); void SetBooleanProperty(AOMBooleanProperty, bool value, bool is_null); void SetFloatProperty(AOMFloatProperty, float value, bool is_null); void SetUIntProperty(AOMUIntProperty, uint32_t value, bool is_null); @@ -297,6 +342,8 @@ Vector<std::pair<AOMUIntProperty, uint32_t>> uint_properties_; HeapVector<std::pair<AOMRelationProperty, Member<AccessibleNode>>> relation_properties_; + HeapVector<std::pair<AOMRelationListProperty, Member<AccessibleNodeList>>> + relation_list_properties_; // This object's owner Element. Member<Element> element_;
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.idl b/third_party/WebKit/Source/core/dom/AccessibleNode.idl index cb5ce8f..0c8356c 100644 --- a/third_party/WebKit/Source/core/dom/AccessibleNode.idl +++ b/third_party/WebKit/Source/core/dom/AccessibleNode.idl
@@ -16,21 +16,26 @@ attribute long? colCount; attribute unsigned long? colIndex; attribute unsigned long? colSpan; + attribute AccessibleNodeList? controls; attribute DOMString? current; + attribute AccessibleNodeList? describedBy; attribute AccessibleNode? details; attribute boolean? disabled; attribute AccessibleNode? errorMessage; attribute boolean? expanded; + attribute AccessibleNodeList? flowTo; attribute boolean? hidden; attribute DOMString? invalid; attribute DOMString? keyShortcuts; attribute DOMString? label; + attribute AccessibleNodeList? labeledBy; attribute unsigned long? level; attribute DOMString? live; attribute boolean? modal; attribute boolean? multiline; attribute boolean? multiselectable; attribute DOMString? orientation; + attribute AccessibleNodeList? owns; attribute DOMString? placeholder; attribute unsigned long? posInSet; attribute DOMString? pressed;
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNodeList.cpp b/third_party/WebKit/Source/core/dom/AccessibleNodeList.cpp new file mode 100644 index 0000000..e905e928 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/AccessibleNodeList.cpp
@@ -0,0 +1,112 @@ +// 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 "core/dom/AccessibleNodeList.h" + +#include "core/dom/AccessibleNode.h" + +namespace blink { + +// The spec doesn't give a limit, but there's no reason to allow relations +// between an arbitrarily large number of other accessible nodes. +static const unsigned kMaxItems = 65536; + +// static +AccessibleNodeList* AccessibleNodeList::Create( + const HeapVector<Member<AccessibleNode>>& nodes) { + AccessibleNodeList* result = new AccessibleNodeList(); + result->nodes_ = nodes; + return result; +} + +AccessibleNodeList::AccessibleNodeList() { + DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled()); +} + +AccessibleNodeList::~AccessibleNodeList() {} + +void AccessibleNodeList::AddOwner(AOMRelationListProperty property, + AccessibleNode* node) { + owners_.push_back(std::make_pair(property, node)); +} + +void AccessibleNodeList::RemoveOwner(AOMRelationListProperty property, + AccessibleNode* node) { + for (size_t i = 0; i < owners_.size(); ++i) { + auto& item = owners_[i]; + if (item.first == property && item.second == node) { + owners_.erase(i); + return; + } + } +} + +AccessibleNode* AccessibleNodeList::item(unsigned offset) const { + if (offset < nodes_.size()) + return nodes_[offset]; + return nullptr; +} + +void AccessibleNodeList::add(AccessibleNode* node, AccessibleNode* before) { + if (nodes_.size() == kMaxItems) + return; + + unsigned index = nodes_.size(); + if (before) { + for (index = 0; index < nodes_.size(); ++index) { + if (nodes_[index] == before) + break; + } + if (index == nodes_.size()) + return; + } + + nodes_.insert(index, node); +} + +void AccessibleNodeList::remove(int index) { + if (index >= 0 && index < static_cast<int>(nodes_.size())) + nodes_.erase(index); +} + +bool AccessibleNodeList::AnonymousIndexedSetter(unsigned index, + AccessibleNode* node, + ExceptionState& state) { + if (!node) { + remove(index); + return true; + } + if (index >= kMaxItems) + return false; + if (index >= nodes_.size()) { + unsigned old_size = nodes_.size(); + nodes_.resize(index + 1); + for (unsigned i = old_size; i < nodes_.size(); ++i) + nodes_[i] = nullptr; + } + nodes_[index] = node; + return true; +} + +unsigned AccessibleNodeList::length() const { + return nodes_.size(); +} + +void AccessibleNodeList::setLength(unsigned new_length) { + if (new_length >= kMaxItems) + return; + nodes_.resize(new_length); +} + +void AccessibleNodeList::NotifyChanged() { + for (auto& owner : owners_) + owner.second->OnRelationListChanged(owner.first); +} + +DEFINE_TRACE(AccessibleNodeList) { + visitor->Trace(nodes_); + visitor->Trace(owners_); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNodeList.h b/third_party/WebKit/Source/core/dom/AccessibleNodeList.h new file mode 100644 index 0000000..130ede4 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/AccessibleNodeList.h
@@ -0,0 +1,53 @@ +// 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 AccessibleNodeList_h +#define AccessibleNodeList_h + +#include "core/CoreExport.h" +#include "platform/bindings/ScriptWrappable.h" + +namespace blink { + +class AccessibleNode; +enum class AOMRelationListProperty; +class ExceptionState; + +// Accessibility Object Model node list +// Explainer: https://github.com/WICG/aom/blob/master/explainer.md +// Spec: https://wicg.github.io/aom/spec/ +class CORE_EXPORT AccessibleNodeList + : public GarbageCollectedFinalized<AccessibleNodeList>, + public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static AccessibleNodeList* Create(const HeapVector<Member<AccessibleNode>>&); + + AccessibleNodeList(); + virtual ~AccessibleNodeList(); + + void AddOwner(AOMRelationListProperty, AccessibleNode*); + void RemoveOwner(AOMRelationListProperty, AccessibleNode*); + + AccessibleNode* item(unsigned offset) const; + void add(AccessibleNode*, AccessibleNode* = nullptr); + void remove(int index); + bool AnonymousIndexedSetter(unsigned, AccessibleNode*, ExceptionState&); + unsigned length() const; + void setLength(unsigned); + + DECLARE_VIRTUAL_TRACE(); + + private: + void NotifyChanged(); + + HeapVector<std::pair<AOMRelationListProperty, Member<AccessibleNode>>> + owners_; + HeapVector<Member<AccessibleNode>> nodes_; +}; + +} // namespace blink + +#endif // AccessibleNodeList_h
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNodeList.idl b/third_party/WebKit/Source/core/dom/AccessibleNodeList.idl new file mode 100644 index 0000000..ec9a2b1 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/AccessibleNodeList.idl
@@ -0,0 +1,17 @@ +// 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. + +// Accessibility Object Model node list +// Explainer: https://github.com/WICG/aom/blob/master/explainer.md +// Spec: https://wicg.github.io/aom/spec/ +[ + Constructor(optional sequence<AccessibleNode> nodes = []), + RuntimeEnabled=AccessibilityObjectModel +] interface AccessibleNodeList { + attribute unsigned long length; + getter AccessibleNode? item(unsigned long index); + [RaisesException] setter void (unsigned long index, AccessibleNode node); + void add(AccessibleNode node, optional AccessibleNode? before = null); + void remove(long index); +};
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn index be72fd34..850f480 100644 --- a/third_party/WebKit/Source/core/dom/BUILD.gn +++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -14,6 +14,8 @@ "AXObjectCacheBase.h", "AccessibleNode.cpp", "AccessibleNode.h", + "AccessibleNodeList.cpp", + "AccessibleNodeList.h", "AncestorList.h", "AnimationWorkletProxyClient.cpp", "AnimationWorkletProxyClient.h",
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp index 945f5e6c..39ebbfaf 100644 --- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp +++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
@@ -75,51 +75,6 @@ AdvanceReadyState(error_occurred ? kErrorOccurred : kReady); } -// Returns true if SRI check passed. -static bool CheckScriptResourceIntegrity(Resource* resource, - ScriptElementBase* element) { - DCHECK_EQ(resource->GetType(), Resource::kScript); - ScriptResource* script_resource = ToScriptResource(resource); - String integrity_attr = element->IntegrityAttributeValue(); - - // It is possible to get back a script resource with integrity metadata - // for a request with an empty integrity attribute. In that case, the - // integrity check should be skipped, so this check ensures that the - // integrity attribute isn't empty in addition to checking if the - // resource has empty integrity metadata. - if (integrity_attr.IsEmpty() || - script_resource->IntegrityMetadata().IsEmpty()) - return true; - - switch (script_resource->IntegrityDisposition()) { - case ResourceIntegrityDisposition::kPassed: - return true; - - case ResourceIntegrityDisposition::kFailed: - // TODO(jww): This should probably also generate a console - // message identical to the one produced by - // CheckSubresourceIntegrity below. See https://crbug.com/585267. - return false; - - case ResourceIntegrityDisposition::kNotChecked: { - if (!resource->ResourceBuffer()) - return true; - - bool passed = SubresourceIntegrity::CheckSubresourceIntegrity( - script_resource->IntegrityMetadata(), element->GetDocument(), - resource->ResourceBuffer()->Data(), - resource->ResourceBuffer()->size(), resource->Url(), *resource); - script_resource->SetIntegrityDisposition( - passed ? ResourceIntegrityDisposition::kPassed - : ResourceIntegrityDisposition::kFailed); - return passed; - } - } - - NOTREACHED(); - return true; -} - void ClassicPendingScript::NotifyFinished(Resource* resource) { // The following SRI checks need to be here because, unfortunately, fetches // are not done purely according to the Fetch spec. In particular, @@ -144,8 +99,19 @@ // // See https://crbug.com/500701 for more information. CheckState(); - if (GetElement()) { - integrity_failure_ = !CheckScriptResourceIntegrity(resource, GetElement()); + ScriptElementBase* element = GetElement(); + if (element) { + GetResource()->CheckResourceIntegrity(element->GetDocument()); + + // It is possible to get back a script resource with integrity metadata + // for a request with an empty integrity attribute. In that case, the + // integrity check should be skipped, so this check ensures that the + // integrity attribute isn't empty in addition to checking if the + // resource has empty integrity metadata. + if (!element->IntegrityAttributeValue().IsEmpty()) { + integrity_failure_ = GetResource()->IntegrityDisposition() != + ResourceIntegrityDisposition::kPassed; + } } // We are now waiting for script streaming to finish.
diff --git a/third_party/WebKit/Source/core/dom/ClientRect.idl b/third_party/WebKit/Source/core/dom/ClientRect.idl index 27230e8..2e9a66e 100644 --- a/third_party/WebKit/Source/core/dom/ClientRect.idl +++ b/third_party/WebKit/Source/core/dom/ClientRect.idl
@@ -29,8 +29,8 @@ // It has since been replaced by DOMRect in CSSOM View Module and // Geometry Interfaces Module: -// https://dev.w3.org/csswg/cssom-view/#extension-to-the-element-interface -// https://dev.w3.org/fxtf/geometry/#DOMRect +// https://drafts.csswg.org/cssom-view/#extension-to-the-element-interface +// https://drafts.fxtf.org/geometry/#DOMRect interface ClientRect { readonly attribute float top;
diff --git a/third_party/WebKit/Source/core/dom/ClientRectList.idl b/third_party/WebKit/Source/core/dom/ClientRectList.idl index 4c3a4db9..31767a6c 100644 --- a/third_party/WebKit/Source/core/dom/ClientRectList.idl +++ b/third_party/WebKit/Source/core/dom/ClientRectList.idl
@@ -30,7 +30,7 @@ // It has since been replace by DOMRectList in CSSOM View Module and // Geometry Interfaces Module: // https://dev.w3.org/csswg/cssom-view/#extension-to-the-element-interface -// https://dev.w3.org/fxtf/geometry/#DOMRectList +// https://drafts.fxtf.org/geometry/#DOMRectList // CSSOM View Module also says: "The DOMRectList interface is at-risk. // The authors of this specification await feedback from implementers
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp index 42783a5..b947258 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -910,16 +910,19 @@ DCHECK(!will_be_parser_executed_); DCHECK(async_exec_type_ != ScriptRunner::kNone); DCHECK(pending_script_->IsExternalOrModule()); + DCHECK_EQ(pending_script_->IsExternal(), is_external_script_); bool error_occurred = false; Script* script = pending_script_->GetSource(NullURL(), error_occurred); const bool wasCanceled = pending_script_->WasCanceled(); + const bool is_external = pending_script_->IsExternal(); DetachPendingScript(); if (error_occurred) { DispatchErrorEvent(); } else if (!wasCanceled) { switch (ExecuteScript(script)) { case ExecuteScriptResult::kShouldFireLoadEvent: - DispatchLoadEvent(); + if (is_external) + DispatchLoadEvent(); break; case ExecuteScriptResult::kShouldFireErrorEvent: DispatchErrorEvent();
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp index 7b35780..761cea8 100644 --- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp +++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
@@ -402,14 +402,16 @@ Node* node, DocumentMarker::MarkerTypes marker_types) { DocumentMarkerVector result; + if (!PossiblyHasMarkers(marker_types)) + return result; MarkerLists* markers = markers_.at(node); if (!markers) return result; - for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { + for (DocumentMarker::MarkerType type : marker_types) { DocumentMarkerList* const list = ListForType(markers, type); - if (!list || list->IsEmpty() || !marker_types.Contains(type)) + if (!list || list->IsEmpty()) continue; result.AppendVector(list->GetMarkers());
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrix.idl b/third_party/WebKit/Source/core/geometry/DOMMatrix.idl index 530347a..5f3378c 100644 --- a/third_party/WebKit/Source/core/geometry/DOMMatrix.idl +++ b/third_party/WebKit/Source/core/geometry/DOMMatrix.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/fxtf/geometry/#DOMMatrix +// https://drafts.fxtf.org/geometry/#DOMMatrix [ Constructor(optional (DOMString or sequence<unrestricted double>) init),
diff --git a/third_party/WebKit/Source/core/geometry/DOMPoint.idl b/third_party/WebKit/Source/core/geometry/DOMPoint.idl index 25556ca..63f084c 100644 --- a/third_party/WebKit/Source/core/geometry/DOMPoint.idl +++ b/third_party/WebKit/Source/core/geometry/DOMPoint.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/fxtf/geometry/#DOMPoint +// https://drafts.fxtf.org/geometry/#DOMPoint [ Constructor(optional unrestricted double x = 0, optional unrestricted double y = 0,
diff --git a/third_party/WebKit/Source/core/geometry/DOMPointInit.idl b/third_party/WebKit/Source/core/geometry/DOMPointInit.idl index 362f0818..e901792 100644 --- a/third_party/WebKit/Source/core/geometry/DOMPointInit.idl +++ b/third_party/WebKit/Source/core/geometry/DOMPointInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/fxtf/geometry/#DOMPoint +// https://drafts.fxtf.org/geometry/#DOMPoint dictionary DOMPointInit { unrestricted double x = 0;
diff --git a/third_party/WebKit/Source/core/geometry/DOMRect.idl b/third_party/WebKit/Source/core/geometry/DOMRect.idl index 241a82c6..6fa18c68 100644 --- a/third_party/WebKit/Source/core/geometry/DOMRect.idl +++ b/third_party/WebKit/Source/core/geometry/DOMRect.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/fxtf/geometry/#DOMRect +// https://drafts.fxtf.org/geometry/#DOMRect [ Constructor(optional unrestricted double x = 0,
diff --git a/third_party/WebKit/Source/core/geometry/DOMRectReadOnly.idl b/third_party/WebKit/Source/core/geometry/DOMRectReadOnly.idl index 598abea..05854af 100644 --- a/third_party/WebKit/Source/core/geometry/DOMRectReadOnly.idl +++ b/third_party/WebKit/Source/core/geometry/DOMRectReadOnly.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://dev.w3.org/fxtf/geometry/#DOMRect +// https://drafts.fxtf.org/geometry/#DOMRect [ Constructor(optional unrestricted double x = 0, optional unrestricted double y = 0,
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index 444ad89..d7a9a68 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -1455,7 +1455,7 @@ layer_tree_view = frame->GetPage()->GetChromeClient().GetWebLayerTreeView(frame); surface_layer_bridge_ = - WTF::MakeUnique<CanvasSurfaceLayerBridge>(this, layer_tree_view); + WTF::MakeUnique<::blink::SurfaceLayerBridge>(this, layer_tree_view); // Creates a placeholder layer first before Surface is created. surface_layer_bridge_->CreateSolidColorLayer(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h index 0221e32..ee473e4 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -44,11 +44,11 @@ #include "platform/bindings/ScriptWrappableVisitor.h" #include "platform/geometry/FloatRect.h" #include "platform/geometry/IntSize.h" -#include "platform/graphics/CanvasSurfaceLayerBridge.h" #include "platform/graphics/GraphicsTypes.h" #include "platform/graphics/GraphicsTypes3D.h" #include "platform/graphics/ImageBufferClient.h" #include "platform/graphics/OffscreenCanvasPlaceholder.h" +#include "platform/graphics/SurfaceLayerBridge.h" #include "platform/heap/Handle.h" #define CanvasDefaultInterpolationQuality kInterpolationLow @@ -75,16 +75,15 @@ typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContext RenderingContext; -class CORE_EXPORT HTMLCanvasElement final - : public HTMLElement, - public ContextLifecycleObserver, - public PageVisibilityObserver, - public CanvasImageSource, - public CanvasRenderingContextHost, - public CanvasSurfaceLayerBridgeObserver, - public ImageBufferClient, - public ImageBitmapSource, - public OffscreenCanvasPlaceholder { +class CORE_EXPORT HTMLCanvasElement final : public HTMLElement, + public ContextLifecycleObserver, + public PageVisibilityObserver, + public CanvasImageSource, + public CanvasRenderingContextHost, + public SurfaceLayerBridgeObserver, + public ImageBufferClient, + public ImageBitmapSource, + public OffscreenCanvasPlaceholder { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(HTMLCanvasElement); USING_PRE_FINALIZER(HTMLCanvasElement, Dispose); @@ -199,7 +198,7 @@ int SourceWidth() override { return size_.Width(); } int SourceHeight() override { return size_.Height(); } - // CanvasSurfaceLayerBridgeObserver implementation + // SurfaceLayerBridgeObserver implementation void OnWebLayerReplaced() override; // ImageBufferClient implementation @@ -243,7 +242,7 @@ String GetIdFromControl(const Element*); // For OffscreenCanvas that controls this html canvas element - CanvasSurfaceLayerBridge* SurfaceLayerBridge() const { + SurfaceLayerBridge* SurfaceLayerBridge() const { return surface_layer_bridge_.get(); } void CreateLayer(); @@ -337,7 +336,7 @@ mutable RefPtr<Image> copied_image_; // Used for OffscreenCanvas that controls this HTML canvas element - std::unique_ptr<CanvasSurfaceLayerBridge> surface_layer_bridge_; + std::unique_ptr<::blink::SurfaceLayerBridge> surface_layer_bridge_; bool did_notify_listeners_for_current_frame_ = false; };
diff --git a/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css b/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css index 0749f6f..53b33d7 100644 --- a/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css +++ b/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css
@@ -29,13 +29,18 @@ padding: 8px; } +#spacer-top { + display: block; + height: var(--arrow-size); +} + #outer-arrow-top { border-color: transparent transparent var(--bubble-border-color) transparent; border-style: solid; border-width: 0px var(--arrow-size) var(--arrow-size) var(--arrow-size); display: block; left: 10px; - margin-top: -2px; + margin-top: 0px; position: absolute; width: 0px; } @@ -46,26 +51,31 @@ border-width: 0px var(--arrow-size) var(--arrow-size) var(--arrow-size); display: block; left: 10px; - margin-bottom: -2px; - position: relative; + margin-top: 1px; + position: absolute; width: 0px; } -.bottom-arrow #outer-arrow-top, .bottom-arrow #inner-arrow-top { +.bottom-arrow #outer-arrow-top, .bottom-arrow #inner-arrow-top, .bottom-arrow #spacer-top { display: none; } -#outer-arrow-bottom, #inner-arrow-bottom { +#outer-arrow-bottom, #inner-arrow-bottom, #spacer-bottom { display: none; } +.bottom-arrow #spacer-bottom { + display: block; + height: var(--arrow-size); +} + .bottom-arrow #outer-arrow-bottom { border-color: var(--bubble-border-color) transparent transparent transparent; border-style: solid; border-width: var(--arrow-size) var(--arrow-size) 0px var(--arrow-size); display: block; left: 10px; - margin-top: 1px; + margin-top: 0px; position: absolute; width: 0px; } @@ -76,15 +86,15 @@ border-width: var(--arrow-size) var(--arrow-size) 0px var(--arrow-size); display: block; left: 10px; - margin-top: -2px; - position: relative; + margin-top: -1px; + position: absolute; width: 0px; } #icon { grid-row: 1 / 3; grid-column: 1; - margin-right: 8px; + -webkit-margin-end: 8px; } #main-message {
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index b051b2da..bbafe297 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -1579,7 +1579,7 @@ "experimental": true }, { - "name": "enableRequestInterception", + "name": "setRequestInterceptionEnabled", "parameters": [ { "name": "enabled", "type": "boolean", "description": "Whether or not HTTP requests should be intercepted and Network.requestIntercepted events sent." } ],
diff --git a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json index 83dad58..df4582c3 100644 --- a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json +++ b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
@@ -93,7 +93,7 @@ { "domain": "Network", "exclude": ["clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookie", "setCookie", "canEmulateNetworkConditions", - "enableRequestInterception", "continueInterceptedRequest"], + "setRequestInterceptionEnabled", "continueInterceptedRequest"], "async": ["getResponseBody"] }, {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp index 6a631dc..6e6ac26b 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp
@@ -965,8 +965,9 @@ true); SetBodyInnerHTML( "<div id='container' style='overflow: scroll; width: 300px; height: " - "300px; border-radius: 5px; background: white; will-change: transform;'>" - " <div style='background-color: blue; width: 2000px; height: " + "300px; background: white; will-change: transform;'>" + " <div style='background-color: blue; clip-path: circle(600px at " + "1000px 1000px); width: 2000px; height: " "2000px;'></div>" "</div>");
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index dfcbd7e..f724ac4 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -595,8 +595,10 @@ ? std::move(state_object) : SerializedScriptValue::NullValue()); - if (history_item) - RestoreScrollPositionAndViewStateForLoadType(frame_load_type); + if (history_item) { + RestoreScrollPositionAndViewStateForLoadType(frame_load_type, + kHistorySameDocumentLoad); + } // We need to scroll to the fragment whether or not a hash change occurred, // since the user might have scrolled since the previous navigation. @@ -1093,11 +1095,13 @@ void FrameLoader::RestoreScrollPositionAndViewState() { if (!frame_->GetPage() || !GetDocumentLoader()) return; - RestoreScrollPositionAndViewStateForLoadType(GetDocumentLoader()->LoadType()); + RestoreScrollPositionAndViewStateForLoadType(GetDocumentLoader()->LoadType(), + kHistoryDifferentDocumentLoad); } void FrameLoader::RestoreScrollPositionAndViewStateForLoadType( - FrameLoadType load_type) { + FrameLoadType load_type, + HistoryLoadType history_load_type) { LocalFrameView* view = frame_->View(); if (!view || !view->LayoutViewportScrollableArea() || !state_machine_.CommittedFirstRealDocumentLoad() || @@ -1115,19 +1119,28 @@ bool should_restore_scale = history_item->PageScaleFactor(); // This tries to balance: - // 1. restoring as soon as possible - // 2. not overriding user scroll (TODO(majidvp): also respect user scale) + // 1. restoring as soon as possible. + // 2. not overriding user scroll (TODO(majidvp): also respect user scale). // 3. detecting clamping to avoid repeatedly popping the scroll position down - // as the page height increases - // 4. ignore clamp detection if we are not restoring scroll or after load - // completes because that may be because the page will never reach its - // previous height + // as the page height increases. + // 4. forcing a layout if necessary to avoid clamping. + // 5. ignoring clamp detection if scroll state is not being restored, if load + // is complete, or if the navigation is same-document (as the new page may + // be smaller than the previous page). bool can_restore_without_clamping = view->LayoutViewportScrollableArea()->ClampScrollOffset( history_item->GetScrollOffset()) == history_item->GetScrollOffset(); + + bool should_force_clamping = + !frame_->IsLoading() || history_load_type == kHistorySameDocumentLoad; + // Here |can_restore_without_clamping| is false, but layout might be necessary + // to ensure correct content size. + if (!can_restore_without_clamping && should_force_clamping) + frame_->GetDocument()->UpdateStyleAndLayout(); + bool can_restore_without_annoying_user = !GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user && - (can_restore_without_clamping || !frame_->IsLoading() || + (can_restore_without_clamping || should_force_clamping || !should_restore_scroll); if (!can_restore_without_annoying_user) return;
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h index 9f1d0e37..d8f5b92 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.h +++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -245,7 +245,8 @@ HistoryItem*, ClientRedirectPolicy, Document*); - void RestoreScrollPositionAndViewStateForLoadType(FrameLoadType); + void RestoreScrollPositionAndViewStateForLoadType(FrameLoadType, + HistoryLoadType); void ScheduleCheckCompleted();
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp index 4fb56ae..5642564 100644 --- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp +++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
@@ -26,6 +26,7 @@ #include "core/loader/resource/ScriptResource.h" +#include "core/frame/SubresourceIntegrity.h" #include "platform/SharedBuffer.h" #include "platform/instrumentation/tracing/web_memory_allocator_dump.h" #include "platform/instrumentation/tracing/web_process_memory_dump.h" @@ -117,4 +118,32 @@ return kNotSharableCrossOrigin; } +void ScriptResource::CheckResourceIntegrity(Document& document) { + // Already checked? Retain existing result. + // + // TODO(vogelheim): If IntegrityDisposition() is kFailed, this should + // probably also generate a console message identical to the one produced + // by the CheckSubresourceIntegrity call below. See crbug.com/585267. + if (IntegrityDisposition() != ResourceIntegrityDisposition::kNotChecked) + return; + + // Loading error occurred? Then result is uncheckable. + if (ErrorOccurred()) + return; + + // No integrity attributes to check? Then we're passing. + if (IntegrityMetadata().IsEmpty()) { + SetIntegrityDisposition(ResourceIntegrityDisposition::kPassed); + return; + } + + CHECK(!!ResourceBuffer()); + bool passed = SubresourceIntegrity::CheckSubresourceIntegrity( + IntegrityMetadata(), document, ResourceBuffer()->Data(), + ResourceBuffer()->size(), Url(), *this); + SetIntegrityDisposition(passed ? ResourceIntegrityDisposition::kPassed + : ResourceIntegrityDisposition::kFailed); + DCHECK_NE(IntegrityDisposition(), ResourceIntegrityDisposition::kNotChecked); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.h b/third_party/WebKit/Source/core/loader/resource/ScriptResource.h index 3fa422f..6309f5e 100644 --- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.h +++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.h
@@ -36,6 +36,7 @@ namespace blink { +class Document; class FetchParameters; class KURL; class ResourceFetcher; @@ -84,6 +85,8 @@ AccessControlStatus CalculateAccessControlStatus() const; + void CheckResourceIntegrity(Document&); + private: class ScriptResourceFactory : public ResourceFactory { public:
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp index e51fe2e0a..6033a80 100644 --- a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp +++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
@@ -43,9 +43,7 @@ return watcher; } -MojoWatcher::~MojoWatcher() { - DCHECK(!handle_.is_valid()); -} +MojoWatcher::~MojoWatcher() {} MojoResult MojoWatcher::cancel() { if (!watcher_handle_.is_valid())
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index f5c3a05..7473695 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -304,6 +304,15 @@ return plugin_data_.Get(); } +void Page::ResetPluginData() { + for (Page* page : AllPages()) { + if (page->plugin_data_) { + page->plugin_data_->ResetPluginData(); + page->NotifyPluginsChanged(); + } + } +} + void Page::SetValidationMessageClient(ValidationMessageClient* client) { validation_message_client_ = client; } @@ -567,15 +576,19 @@ } break; case SettingsDelegate::kPluginsChange: { - HeapVector<Member<PluginsChangedObserver>, 32> observers; - CopyToVector(plugins_changed_observers_, observers); - for (PluginsChangedObserver* observer : observers) - observer->PluginsChanged(); + NotifyPluginsChanged(); break; } } } +void Page::NotifyPluginsChanged() const { + HeapVector<Member<PluginsChangedObserver>, 32> observers; + CopyToVector(plugins_changed_observers_, observers); + for (PluginsChangedObserver* observer : observers) + observer->PluginsChanged(); +} + void Page::UpdateAcceleratedCompositingSettings() { for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) {
diff --git a/third_party/WebKit/Source/core/page/Page.h b/third_party/WebKit/Source/core/page/Page.h index 2543d5d..cc00c32 100644 --- a/third_party/WebKit/Source/core/page/Page.h +++ b/third_party/WebKit/Source/core/page/Page.h
@@ -134,9 +134,16 @@ ViewportDescription GetViewportDescription() const; - static void RefreshPlugins(); + // Returns the plugin data associated with |main_frame_origin|. PluginData* GetPluginData(SecurityOrigin* main_frame_origin); + // Refreshes the browser-side plugin cache. + static void RefreshPlugins(); + + // Resets the plugin data for all pages in the renderer process and notifies + // PluginsChangedObservers. + static void ResetPluginData(); + EditorClient& GetEditorClient() const { return *editor_client_; } SpellCheckerClient& GetSpellCheckerClient() const { return *spell_checker_client_; @@ -305,6 +312,9 @@ // ScopedPageSuspender helpers. void SetSuspended(bool); + // Notify |plugins_changed_observers_| that plugins have changed. + void NotifyPluginsChanged() const; + Member<PageAnimator> animator_; const Member<AutoscrollController> autoscroll_controller_; Member<ChromeClient> chrome_client_;
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp index 3d2dadb..a18f19f 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp +++ b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
@@ -12,6 +12,7 @@ #include "core/page/PagePopupClient.h" #include "platform/LayoutTestSupport.h" #include "platform/graphics/paint/CullRect.h" +#include "platform/text/PlatformLocale.h" namespace blink { @@ -129,7 +130,7 @@ SubstituteData(data, "text/html", "UTF-8", KURL(), kForceSynchronousLoad))); - Element& container = BubbleContainer(); + Element& container = GetElementById("container"); if (LayoutTestSupport::IsRunningLayoutTest()) container.SetInlineStyleProperty(CSSPropertyTransition, "none"); // Get the size to decide position later. @@ -137,8 +138,8 @@ bubble_size_ = container.VisibleBoundsInVisualViewport().Size(); // Add one because the content sometimes exceeds the exact width due to // rounding errors. - container.SetInlineStyleProperty(CSSPropertyMinWidth, - bubble_size_.Width() + 1, + bubble_size_.Expand(1, 0); + container.SetInlineStyleProperty(CSSPropertyMinWidth, bubble_size_.Width(), CSSPrimitiveValue::UnitType::kPixels); } @@ -146,11 +147,15 @@ DCHECK(data); PagePopupClient::AddString("<!DOCTYPE html><html><head><style>", data); data->Append(Platform::Current()->GetDataResource("validation_bubble.css")); + PagePopupClient::AddString("</style></head>", data); PagePopupClient::AddString( - "</style></head><body>" + Locale::DefaultLocale().IsRTL() ? "<body dir=rtl>" : "<body dir=ltr>", + data); + PagePopupClient::AddString( "<div id=container>" "<div id=outer-arrow-top></div>" "<div id=inner-arrow-top></div>" + "<div id=spacer-top></div>" "<main id=bubble-body>", data); data->Append(Platform::Current()->GetDataResource("input_alert.svg")); @@ -168,16 +173,18 @@ "</div></main>" "<div id=outer-arrow-bottom></div>" "<div id=inner-arrow-bottom></div>" + "<div id=spacer-bottom></div>" "</div></body></html>\n", data); } -Element& ValidationMessageOverlayDelegate::BubbleContainer() const { - Element* container = ToLocalFrame(page_->MainFrame()) - ->GetDocument() - ->getElementById("container"); - DCHECK(container) << "Failed to load the document?"; - return *container; +Element& ValidationMessageOverlayDelegate::GetElementById( + const AtomicString& id) const { + Element* element = + ToLocalFrame(page_->MainFrame())->GetDocument()->getElementById(id); + DCHECK(element) << "No element with id=" << id + << ". Failed to load the document?"; + return *element; } void ValidationMessageOverlayDelegate::AdjustBubblePosition( @@ -196,7 +203,7 @@ else if (bubble_x + bubble_size_.Width() > view_size.Width()) bubble_x = view_size.Width() - bubble_size_.Width(); - Element& container = BubbleContainer(); + Element& container = GetElementById("container"); container.SetInlineStyleProperty(CSSPropertyLeft, bubble_x, CSSPrimitiveValue::UnitType::kPixels); container.SetInlineStyleProperty(CSSPropertyTop, bubble_y, @@ -208,7 +215,54 @@ else container.removeAttribute(HTMLNames::classAttr); - // TODO(tkent): Adjust arrow position. + // Should match to --arrow-size in validation_bubble.css. + const int kArrowSize = 8; + const int kArrowMargin = 10; + const int kMinArrowAnchorX = kArrowSize + kArrowMargin; + double max_arrow_anchor_x = + bubble_size_.Width() - (kArrowSize + kArrowMargin); + double arrow_anchor_x; + const int kOffsetToAnchorRect = 8; + double anchor_rect_center = anchor_rect.X() + anchor_rect.Width() / 2; + if (!Locale::DefaultLocale().IsRTL()) { + double anchor_rect_left = anchor_rect.X() + kOffsetToAnchorRect; + if (anchor_rect_left > anchor_rect_center) + anchor_rect_left = anchor_rect_center; + + arrow_anchor_x = kMinArrowAnchorX; + if (bubble_x + arrow_anchor_x < anchor_rect_left) { + arrow_anchor_x = anchor_rect_left - bubble_x; + if (arrow_anchor_x > max_arrow_anchor_x) + arrow_anchor_x = max_arrow_anchor_x; + } + } else { + double anchor_rect_right = anchor_rect.MaxX() - kOffsetToAnchorRect; + if (anchor_rect_right < anchor_rect_center) + anchor_rect_right = anchor_rect_center; + + arrow_anchor_x = max_arrow_anchor_x; + if (bubble_x + arrow_anchor_x > anchor_rect_right) { + arrow_anchor_x = anchor_rect_right - bubble_x; + if (arrow_anchor_x < kMinArrowAnchorX) + arrow_anchor_x = kMinArrowAnchorX; + } + } + double arrow_x = arrow_anchor_x - kArrowSize; + if (show_bottom_arrow) { + GetElementById("outer-arrow-bottom") + .SetInlineStyleProperty(CSSPropertyLeft, arrow_x, + CSSPrimitiveValue::UnitType::kPixels); + GetElementById("inner-arrow-bottom") + .SetInlineStyleProperty(CSSPropertyLeft, arrow_x, + CSSPrimitiveValue::UnitType::kPixels); + } else { + GetElementById("outer-arrow-top") + .SetInlineStyleProperty(CSSPropertyLeft, arrow_x, + CSSPrimitiveValue::UnitType::kPixels); + GetElementById("inner-arrow-top") + .SetInlineStyleProperty(CSSPropertyLeft, arrow_x, + CSSPrimitiveValue::UnitType::kPixels); + } } } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.h b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.h index cdf13342..998c8a61 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.h +++ b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.h
@@ -49,7 +49,7 @@ void UpdateFrameViewState(const PageOverlay&, const IntSize& view_size); void EnsurePage(const PageOverlay&, const IntSize& view_size); void WriteDocument(SharedBuffer*); - Element& BubbleContainer() const; + Element& GetElementById(const AtomicString&) const; void AdjustBubblePosition(const IntSize& view_size); // An internal Page and a ChromeClient for it.
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp index e4c63b0..0fc0961 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp
@@ -1122,11 +1122,6 @@ MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText); } -TEST_P(NonCompositedMainThreadScrollingReasonTest, BorderRadiusTest) { - TestNonCompositedReasons("border-radius", - MainThreadScrollingReason::kHasBorderRadius); -} - TEST_P(NonCompositedMainThreadScrollingReasonTest, ClipTest) { TestNonCompositedReasons("clip", MainThreadScrollingReason::kHasClipRelatedProperty); @@ -1182,9 +1177,8 @@ } TEST_P(NonCompositedMainThreadScrollingReasonTest, LCDTextEnabledTest) { - TestNonCompositedReasons("transparent border-radius", - MainThreadScrollingReason::kHasOpacityAndLCDText | - MainThreadScrollingReason::kHasBorderRadius); + TestNonCompositedReasons("transparent", + MainThreadScrollingReason::kHasOpacityAndLCDText); } TEST_P(NonCompositedMainThreadScrollingReasonTest, BoxShadowTest) { @@ -1249,8 +1243,7 @@ ToLayoutBoxModelObject(container2->GetLayoutObject()) ->GetScrollableArea(); ASSERT_TRUE(scrollable_area2); - EXPECT_TRUE(scrollable_area2->GetNonCompositedMainThreadScrollingReasons() & - MainThreadScrollingReason::kHasBorderRadius); + ASSERT_TRUE(scrollable_area2->UsesCompositedScrolling()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp index 238cf7c9d..316cf55 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
@@ -500,8 +500,15 @@ } else { const auto* ancestor_overflow_clip = ancestor_properties->OverflowClip(); if (ancestor_overflow_clip) { - DCHECK_EQ(destination_property_tree_state.Clip(), - ancestor_overflow_clip->Parent()); + if (const auto* ancestor_rounded_clip = + ancestor_properties->InnerBorderRadiusClip()) { + DCHECK_EQ(destination_property_tree_state.Clip(), + ancestor_rounded_clip->Parent()); + DCHECK_EQ(ancestor_rounded_clip, ancestor_overflow_clip->Parent()); + } else { + DCHECK_EQ(destination_property_tree_state.Clip(), + ancestor_overflow_clip->Parent()); + } destination_property_tree_state.SetClip(ancestor_overflow_clip); } }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp index 04fc15e..ab812bf 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -1967,11 +1967,6 @@ // layer->layoutObject().style()->hasBorderDecoration() (missing background // behind dashed borders). Resolve this case, or not, and update this check // with the results. - if (layer->GetLayoutObject().Style()->HasBorderRadius()) { - non_composited_main_thread_scrolling_reasons_ |= - MainThreadScrollingReason::kHasBorderRadius; - needs_composited_scrolling = false; - } if (layer->GetLayoutObject().HasClip() || layer->HasDescendantWithClipPath() || layer->HasAncestorWithClipPath()) { non_composited_main_thread_scrolling_reasons_ |=
diff --git a/third_party/WebKit/Source/core/xml/XPathGrammar.y b/third_party/WebKit/Source/core/xml/XPathGrammar.y index 461cd66..6e9c393 100644 --- a/third_party/WebKit/Source/core/xml/XPathGrammar.y +++ b/third_party/WebKit/Source/core/xml/XPathGrammar.y
@@ -49,9 +49,7 @@ #define YYDEBUG 0 #define YYMAXDEPTH 10000 -using namespace blink; -using namespace XPath; - +using blink::XPath::Step; %} %pure-parser @@ -73,7 +71,7 @@ %{ -static int xpathyylex(YYSTYPE* yylval) { return Parser::Current()->Lex(yylval); } +static int xpathyylex(YYSTYPE* yylval) { return blink::XPath::Parser::Current()->Lex(yylval); } static void xpathyyerror(void*, const char*) { } %} @@ -140,7 +138,7 @@ AbsoluteLocationPath: '/' { - $$ = new LocationPath; + $$ = new blink::XPath::LocationPath; } | '/' RelativeLocationPath @@ -158,7 +156,7 @@ RelativeLocationPath: Step { - $$ = new LocationPath; + $$ = new blink::XPath::LocationPath; $$->AppendStep($1); } | @@ -274,13 +272,13 @@ PredicateList: Predicate { - $$ = new blink::HeapVector<blink::Member<Predicate>>; - $$->push_back(new Predicate($1)); + $$ = new blink::HeapVector<blink::Member<blink::XPath::Predicate>>; + $$->push_back(new blink::XPath::Predicate($1)); } | PredicateList Predicate { - $$->push_back(new Predicate($2)); + $$->push_back(new blink::XPath::Predicate($2)); } ; @@ -313,7 +311,7 @@ PrimaryExpr: VARIABLEREFERENCE { - $$ = new VariableReference(*$1); + $$ = new blink::XPath::VariableReference(*$1); parser->DeleteString($1); } | @@ -324,13 +322,13 @@ | LITERAL { - $$ = new StringExpression(*$1); + $$ = new blink::XPath::StringExpression(*$1); parser->DeleteString($1); } | NUMBER { - $$ = new Number($1->ToDouble()); + $$ = new blink::XPath::Number($1->ToDouble()); parser->DeleteString($1); } | @@ -340,7 +338,7 @@ FunctionCall: FUNCTIONNAME '(' ')' { - $$ = CreateFunction(*$1); + $$ = blink::XPath::CreateFunction(*$1); if (!$$) YYABORT; parser->DeleteString($1); @@ -348,7 +346,7 @@ | FUNCTIONNAME '(' ArgumentList ')' { - $$ = CreateFunction(*$1, *$3); + $$ = blink::XPath::CreateFunction(*$1, *$3); if (!$$) YYABORT; parser->DeleteString($1); @@ -358,7 +356,7 @@ ArgumentList: Argument { - $$ = new blink::HeapVector<blink::Member<Expression>>; + $$ = new blink::HeapVector<blink::Member<blink::XPath::Expression>>; $$->push_back($1); } | @@ -377,7 +375,7 @@ | UnionExpr '|' PathExpr { - $$ = new Union; + $$ = new blink::XPath::Union; $$->AddSubExpression($1); $$->AddSubExpression($3); } @@ -419,7 +417,7 @@ | OrExpr OR AndExpr { - $$ = new LogicalOp(LogicalOp::kOP_Or, $1, $3); + $$ = new blink::XPath::LogicalOp(blink::XPath::LogicalOp::kOP_Or, $1, $3); } ; @@ -428,7 +426,7 @@ | AndExpr AND EqualityExpr { - $$ = new LogicalOp(LogicalOp::kOP_And, $1, $3); + $$ = new blink::XPath::LogicalOp(blink::XPath::LogicalOp::kOP_And, $1, $3); } ; @@ -437,7 +435,7 @@ | EqualityExpr EQOP RelationalExpr { - $$ = new EqTestOp($2, $1, $3); + $$ = new blink::XPath::EqTestOp($2, $1, $3); } ; @@ -446,7 +444,7 @@ | RelationalExpr RELOP AdditiveExpr { - $$ = new EqTestOp($2, $1, $3); + $$ = new blink::XPath::EqTestOp($2, $1, $3); } ; @@ -455,12 +453,12 @@ | AdditiveExpr PLUS MultiplicativeExpr { - $$ = new NumericOp(NumericOp::kOP_Add, $1, $3); + $$ = new blink::XPath::NumericOp(blink::XPath::NumericOp::kOP_Add, $1, $3); } | AdditiveExpr MINUS MultiplicativeExpr { - $$ = new NumericOp(NumericOp::kOP_Sub, $1, $3); + $$ = new blink::XPath::NumericOp(blink::XPath::NumericOp::kOP_Sub, $1, $3); } ; @@ -469,7 +467,7 @@ | MultiplicativeExpr MULOP UnaryExpr { - $$ = new NumericOp($2, $1, $3); + $$ = new blink::XPath::NumericOp($2, $1, $3); } ; @@ -478,7 +476,7 @@ | MINUS UnaryExpr { - $$ = new Negative; + $$ = new blink::XPath::Negative; $$->AddSubExpression($2); } ;
diff --git a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp index a07e29b..448d3ce 100644 --- a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
@@ -436,6 +436,8 @@ void XMLDocumentParser::NotifyFinished(Resource* unused_resource) { DCHECK_EQ(unused_resource, pending_script_); + pending_script_->CheckResourceIntegrity(*GetDocument()); + ScriptSourceCode source_code(pending_script_.Get()); bool error_occurred = pending_script_->ErrorOccurred(); bool was_canceled = pending_script_->WasCanceled();
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js index b4d7591..b41f100b 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -1337,6 +1337,7 @@ handleAction(context, actionId) { switch (actionId) { case 'console.show': + InspectorFrontendHost.bringToFront(); Common.console.show(); return true; case 'console.clear':
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 33288ac9..5e5968a 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -311,8 +311,10 @@ } _registerForwardedShortcuts() { - /** @const */ var forwardedActions = - ['main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show']; + /** @const */ var forwardedActions = [ + 'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show', + 'console.show' + ]; var actionKeys = UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey); InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js index cc6679d..ca8ee94 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -681,7 +681,7 @@ * @return {boolean} */ isNavigationRequest() { - var pageLoad = NetworkLog.networkLog.pageLoadForRequest(this._request); + var pageLoad = NetworkLog.PageLoad.forRequest(this._request); return pageLoad ? pageLoad.mainRequest === this._request : false; } @@ -920,7 +920,8 @@ var request = this._request; var initiator = NetworkLog.networkLog.initiatorInfoForRequest(request); - if (request.timing && request.timing.pushStart) + var timing = request.timing; + if (timing && timing.pushStart) cell.appendChild(createTextNode(Common.UIString('Push / '))); switch (initiator.type) { case SDK.NetworkRequest.InitiatorType.Parser:
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js index 423f4c97..343b688 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
@@ -52,7 +52,7 @@ this._filterBar.show(this.element); this.setDefaultFocusedChild(this._filterBar); - this._filmStripPlaceholderElement = this.element.createChild('div'); + this._filmStripPlaceholderElement = this.element.createChild('div', 'network-film-strip-placeholder'); // Create top overview component. this._overviewPane = new PerfUI.TimelineOverviewPane('network');
diff --git a/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js b/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js index 4a76e3b..9654057f 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/RequestTimingView.js
@@ -305,7 +305,8 @@ } /** - * param {string} title + * @param {string} title + * @return {!Element} */ function createHeader(title) { var dataHeader = tableElement.createChild('tr', 'network-timing-table-header');
diff --git a/third_party/WebKit/Source/devtools/front_end/network/networkPanel.css b/third_party/WebKit/Source/devtools/front_end/network/networkPanel.css index 80f149b2..e103b2f 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/networkPanel.css +++ b/third_party/WebKit/Source/devtools/front_end/network/networkPanel.css
@@ -120,6 +120,10 @@ flex: none !important; } +.network-film-strip-placeholder { + flex-shrink: 0; +} + .network-blocked-urls { border-top: 1px solid #dadada; flex: 104px 0 0;
diff --git a/third_party/WebKit/Source/devtools/front_end/network_log/HAREntry.js b/third_party/WebKit/Source/devtools/front_end/network_log/HAREntry.js index 371f2d8..8fbc832 100644 --- a/third_party/WebKit/Source/devtools/front_end/network_log/HAREntry.js +++ b/third_party/WebKit/Source/devtools/front_end/network_log/HAREntry.js
@@ -73,7 +73,7 @@ if (this._request.connectionId !== '0') entry.connection = this._request.connectionId; - var page = NetworkLog.networkLog.pageLoadForRequest(this._request); + var page = NetworkLog.PageLoad.forRequest(this._request); if (page) entry.pageref = 'page_' + page.id; return entry; @@ -305,7 +305,7 @@ var pages = []; for (var i = 0; i < this._requests.length; ++i) { var request = this._requests[i]; - var page = NetworkLog.networkLog.pageLoadForRequest(request); + var page = NetworkLog.PageLoad.forRequest(request); if (!page || seenIdentifiers[page.id]) continue; seenIdentifiers[page.id] = true;
diff --git a/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js b/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js index e473e57..7d1df3b 100644 --- a/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js +++ b/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
@@ -265,14 +265,6 @@ return request[NetworkLog.NetworkLog._initiatorDataSymbol].request; } - /** - * @param {!SDK.NetworkRequest} request - * @return {?NetworkLog.PageLoad} - */ - pageLoadForRequest(request) { - return request[NetworkLog.NetworkLog._pageLoadForRequestSymbol] || null; - } - _willReloadPage() { if (!Common.moduleSetting('network_log.preserve-log').get()) this.reset(); @@ -314,7 +306,7 @@ oldRequestsSet.delete(request); this._requests.push(request); this._requestsSet.add(request); - request[NetworkLog.NetworkLog._pageLoadForRequestSymbol] = currentPageLoad; + currentPageLoad.bindRequest(request); this.dispatchEventToListeners(NetworkLog.NetworkLog.Events.RequestAdded, request); } @@ -340,7 +332,7 @@ var manager = SDK.NetworkManager.forRequest(request); var pageLoad = manager ? this._pageLoadForManager.get(manager) : null; if (pageLoad) - request[NetworkLog.NetworkLog._pageLoadForRequestSymbol] = pageLoad; + pageLoad.bindRequest(request); this.dispatchEventToListeners(NetworkLog.NetworkLog.Events.RequestAdded, request); } @@ -410,9 +402,25 @@ this.contentLoadTime; this.mainRequest = mainRequest; } + + /** + * @param {!SDK.NetworkRequest} request + * @return {?NetworkLog.PageLoad} + */ + static forRequest(request) { + return request[NetworkLog.PageLoad._pageLoadForRequestSymbol] || null; + } + + /** + * @param {!SDK.NetworkRequest} request + */ + bindRequest(request) { + request[NetworkLog.PageLoad._pageLoadForRequestSymbol] = this; + } }; NetworkLog.PageLoad._lastIdentifier = 0; +NetworkLog.PageLoad._pageLoadForRequestSymbol = Symbol('PageLoadForRequest'); /** @typedef {!{initiators: !Set<!SDK.NetworkRequest>, initiated: !Set<!SDK.NetworkRequest>}} */ NetworkLog.NetworkLog.InitiatorGraph; @@ -427,7 +435,6 @@ NetworkLog.NetworkLog._InitiatorInfo; NetworkLog.NetworkLog._initiatorDataSymbol = Symbol('InitiatorData'); -NetworkLog.NetworkLog._pageLoadForRequestSymbol = Symbol('PageLoadForRequest'); NetworkLog.NetworkLog._events = Symbol('NetworkLog.NetworkLog.events'); /** @type {!NetworkLog.NetworkLog} */
diff --git a/third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js b/third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js index 90b98ea..fe03534 100644 --- a/third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js
@@ -312,6 +312,7 @@ * @return {boolean} */ handleAction(context, actionId) { + InspectorFrontendHost.bringToFront(); QuickOpen.QuickOpen.show('>'); return true; }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js index b91730f1..3b9dca2 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js
@@ -36,9 +36,11 @@ var quota = this._reportView.appendSection(Common.UIString('Usage')); this._quotaRow = quota.appendRow(); + this._quotaUsage = null; this._pieChart = new PerfUI.PieChart(110, Number.bytesToString, true); - this._pieChartLegend = createElementWithClass('div', 'legend'); + this._pieChartLegend = createElement('div'); var usageBreakdownRow = quota.appendRow(); + usageBreakdownRow.classList.add('usage-breakdown-row'); usageBreakdownRow.appendChild(this._pieChart.element); usageBreakdownRow.appendChild(this._pieChartLegend); @@ -196,25 +198,24 @@ this._quotaRow.textContent = Common.UIString( '%s used out of %s storage quota', Number.bytesToString(response.usage), Number.bytesToString(response.quota)); - this._resetPieChart(response.usage); - var colorIndex = 0; - for (var usageForType of response.usageBreakdown) { - if (!usageForType.usage) - continue; - if (colorIndex === this._pieColors.length) - colorIndex = 0; - this._appendLegendRow( - this._getStorageTypeName(usageForType.storageType), usageForType.usage, this._pieColors[colorIndex++]); + if (!this._quotaUsage || this._quotaUsage !== response.usage) { + this._quotaUsage = response.usage; + this._resetPieChart(response.usage); + var colorIndex = 0; + for (var usageForType of response.usageBreakdown) { + if (!usageForType.usage) + continue; + if (colorIndex === this._pieColors.length) + colorIndex = 0; + this._appendLegendRow( + this._getStorageTypeName(usageForType.storageType), usageForType.usage, this._pieColors[colorIndex++]); + } } this._usageUpdatedForTest(response.usage, response.quota, response.usageBreakdown); this.update(); } - _formatPieChartBytes(value) { - return Number.bytesToString(value); - } - /** * @param {number} total */
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/clearStorageView.css b/third_party/WebKit/Source/devtools/front_end/resources/clearStorageView.css index a2ba5f4..ae8e397 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/clearStorageView.css +++ b/third_party/WebKit/Source/devtools/front_end/resources/clearStorageView.css
@@ -23,6 +23,10 @@ display: inline; } +.usage-breakdown-row { + min-width: fit-content; +} + .usage-breakdown-legend-title { display: inline-block; }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js index 771f0819..a5661f15 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
@@ -463,18 +463,22 @@ } /** - * @param {!Protocol.Network.ResourceTiming|undefined} x + * @param {!Protocol.Network.ResourceTiming|undefined} timingInfo */ - set timing(x) { - if (x && !this._fromMemoryCache) { - // Take startTime and responseReceivedTime from timing data for better accuracy. - // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis. - this._startTime = x.requestTime; - this._responseReceivedTime = x.requestTime + x.receiveHeadersEnd / 1000.0; + set timing(timingInfo) { + if (!timingInfo || this._fromMemoryCache) + return; + // Take startTime and responseReceivedTime from timing data for better accuracy. + // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis. + this._startTime = timingInfo.requestTime; + var headersReceivedTime = timingInfo.requestTime + timingInfo.receiveHeadersEnd / 1000.0; + if ((this._responseReceivedTime || -1) < 0 || this._responseReceivedTime > headersReceivedTime) + this._responseReceivedTime = headersReceivedTime; + if (this._startTime > this._responseReceivedTime) + this._responseReceivedTime = this._startTime; - this._timing = x; - this.dispatchEventToListeners(SDK.NetworkRequest.Events.TimingChanged, this); - } + this._timing = timingInfo; + this.dispatchEventToListeners(SDK.NetworkRequest.Events.TimingChanged, this); } /** @@ -668,10 +672,24 @@ /** * @return {string} */ + _filteredProtocolName() { + var protocol = this.protocol.toLowerCase(); + if (protocol === 'h2') + return 'http/2.0'; + return protocol.replace(/^http\/2(\.0)?\+/, 'http/2.0+'); + } + + /** + * @return {string} + */ requestHttpVersion() { var headersText = this.requestHeadersText(); - if (!headersText) - return this.requestHeaderValue('version') || this.requestHeaderValue(':version') || 'unknown'; + if (!headersText) { + var version = this.requestHeaderValue('version') || this.requestHeaderValue(':version'); + if (version) + return version; + return this._filteredProtocolName(); + } var firstLine = headersText.split(/\r\n/)[0]; var match = firstLine.match(/(HTTP\/\d+\.\d+)$/); return match ? match[1] : 'HTTP/0.9'; @@ -818,8 +836,12 @@ */ responseHttpVersion() { var headersText = this._responseHeadersText; - if (!headersText) - return this.responseHeaderValue('version') || this.responseHeaderValue(':version') || 'unknown'; + if (!headersText) { + var version = this.responseHeaderValue('version') || this.responseHeaderValue(':version'); + if (version) + return version; + return this._filteredProtocolName(); + } var firstLine = headersText.split(/\r\n/)[0]; var match = firstLine.match(/^(HTTP\/\d+\.\d+)/); return match ? match[1] : 'HTTP/0.9';
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp index 60a4a89e..a0d2f7a 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -1264,16 +1264,18 @@ // void AXLayoutObject::AriaOwnsElements(AXObjectVector& owns) const { - AccessibilityChildrenFromAttribute(aria_ownsAttr, owns); + AccessibilityChildrenFromAOMProperty(AOMRelationListProperty::kOwns, owns); } void AXLayoutObject::AriaDescribedbyElements( AXObjectVector& describedby) const { - AccessibilityChildrenFromAttribute(aria_describedbyAttr, describedby); + AccessibilityChildrenFromAOMProperty(AOMRelationListProperty::kDescribedBy, + describedby); } void AXLayoutObject::AriaLabelledbyElements(AXObjectVector& labelledby) const { - AccessibilityChildrenFromAttribute(aria_labelledbyAttr, labelledby); + AccessibilityChildrenFromAOMProperty(AOMRelationListProperty::kLabeledBy, + labelledby); } bool AXLayoutObject::AriaHasPopup() const { @@ -2257,7 +2259,9 @@ return false; HeapVector<Member<Element>> elements; - ElementsFromAttribute(elements, aria_controlsAttr); + if (!HasAOMPropertyOrARIAAttribute(AOMRelationListProperty::kControls, + elements)) + return false; for (const auto& element : elements) { AXObject* tab_panel = AxObjectCache().GetOrCreate(element);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp index 5976ccf4..b806d32 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -30,6 +30,7 @@ #include "core/InputTypeNames.h" #include "core/dom/AccessibleNode.h" +#include "core/dom/AccessibleNodeList.h" #include "core/dom/Element.h" #include "core/dom/FlatTreeTraversal.h" #include "core/dom/NodeTraversal.h" @@ -268,6 +269,34 @@ sparse_attribute_client_.AddObjectAttribute(attribute, *target_obj); } + void AddRelationListProperty(AOMRelationListProperty property, + const AccessibleNodeList& relations) override { + AXObjectVectorAttribute attribute; + switch (property) { + case AOMRelationListProperty::kControls: + attribute = AXObjectVectorAttribute::kAriaControls; + break; + case AOMRelationListProperty::kFlowTo: + attribute = AXObjectVectorAttribute::kAriaFlowTo; + break; + default: + return; + } + + HeapVector<Member<AXObject>> objects; + for (size_t i = 0; i < relations.length(); ++i) { + AccessibleNode* accessible_node = relations.item(i); + if (accessible_node) { + Element* element = accessible_node->element(); + AXObject* ax_element = ax_object_cache_->GetOrCreate(element); + if (ax_element && !ax_element->AccessibilityIsIgnored()) + objects.push_back(ax_element); + } + } + + sparse_attribute_client_.AddObjectVectorAttribute(attribute, objects); + } + private: Persistent<AXObjectCacheImpl> ax_object_cache_; AXSparseAttributeClient& sparse_attribute_client_; @@ -773,18 +802,20 @@ return kUnknownRole; } -void AXNodeObject::AccessibilityChildrenFromAttribute( - QualifiedName attr, +void AXNodeObject::AccessibilityChildrenFromAOMProperty( + AOMRelationListProperty property, AXObject::AXObjectVector& children) const { HeapVector<Member<Element>> elements; - ElementsFromAttribute(elements, attr); + if (!HasAOMPropertyOrARIAAttribute(property, elements)) + return; AXObjectCacheImpl& cache = AxObjectCache(); for (const auto& element : elements) { if (AXObject* child = cache.GetOrCreate(element)) { // Only aria-labelledby and aria-describedby can target hidden elements. - if (child->AccessibilityIsIgnored() && attr != aria_labelledbyAttr && - attr != aria_labeledbyAttr && attr != aria_describedbyAttr) { + if (child->AccessibilityIsIgnored() && + property != AOMRelationListProperty::kLabeledBy && + property != AOMRelationListProperty::kDescribedBy) { continue; } children.push_back(child); @@ -792,6 +823,36 @@ } } +bool AXNodeObject::IsMultiline() const { + Node* node = this->GetNode(); + if (!node) + return false; + + const AccessibilityRole role = RoleValue(); + const bool is_edit_box = role == kSearchBoxRole || role == kTextFieldRole; + if (!IsEditable() && !is_edit_box) + return false; // Doesn't support multiline. + + // Supports aria-multiline, so check for attribute. + bool is_multiline = false; + if (HasAOMPropertyOrARIAAttribute(AOMBooleanProperty::kMultiline, + is_multiline)) { + return is_multiline; + } + + // Default for <textarea> is true. + if (isHTMLTextAreaElement(*node)) + return true; + + // Default for other edit boxes is false, including for ARIA, says CORE-AAM. + if (is_edit_box) + return false; + + // If root of contenteditable area and no ARIA role of textbox/searchbox used, + // default to multiline=true which is what the default behavior is. + return HasContentEditableAttributeSet(); +} + // This only returns true if this is the element that actually has the // contentEditable attribute set, unlike node->hasEditableStyle() which will // also return true if an ancestor is editable. @@ -805,6 +866,9 @@ EqualIgnoringASCIICase(content_editable_value, "true"); } +// TODO(aleventhal) Find a more appropriate name or consider returning false +// for everything but a searchbox or textfield, as a combobox and spinbox +// can contain a field but should not be considered edit controls themselves. bool AXNodeObject::IsTextControl() const { if (HasContentEditableAttributeSet()) return true; @@ -2536,14 +2600,30 @@ void AXNodeObject::ComputeAriaOwnsChildren( HeapVector<Member<AXObject>>& owned_children) const { + Vector<String> id_vector; + if (!CanHaveChildren() || IsNativeTextControl() || + HasContentEditableAttributeSet()) { + AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); + return; + } + + HeapVector<Member<Element>> elements; + if (HasAOMProperty(AOMRelationListProperty::kOwns, elements)) { + AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); + + for (const auto& element : elements) { + AXObject* ax_element = ax_object_cache_->GetOrCreate(&*element); + if (ax_element && !ax_element->AccessibilityIsIgnored()) + owned_children.push_back(ax_element); + } + + return; + } + if (!HasAttribute(aria_ownsAttr)) return; - Vector<String> id_vector; - if (CanHaveChildren() && !IsNativeTextControl() && - !HasContentEditableAttributeSet()) - TokenVectorFromAttribute(id_vector, aria_ownsAttr); - + TokenVectorFromAttribute(id_vector, aria_ownsAttr); AxObjectCache().UpdateAriaOwns(this, id_vector, owned_children); } @@ -3068,6 +3148,28 @@ // aria-describedby overrides any other accessible description, from: // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html + // AOM version. + HeapVector<Member<Element>> elements; + if (HasAOMProperty(AOMRelationListProperty::kDescribedBy, elements)) { + AXObjectSet visited; + description = TextFromElements(true, visited, elements, related_objects); + if (!description.IsNull()) { + if (description_sources) { + DescriptionSource& source = description_sources->back(); + source.type = description_from; + source.related_objects = *related_objects; + source.text = description; + found_description = true; + } else { + return description; + } + } else if (description_sources) { + description_sources->back().invalid = true; + } + } + + // aria-describedby overrides any other accessible description, from: + // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html const AtomicString& aria_describedby = GetAttribute(aria_describedbyAttr); if (!aria_describedby.IsNull()) { if (description_sources)
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h index 5e03781..78ab541 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h
@@ -70,8 +70,8 @@ String AriaAccessibilityDescription() const; String AriaAutoComplete() const; AccessibilityRole DetermineAriaRoleAttribute() const; - void AccessibilityChildrenFromAttribute(QualifiedName attr, - AXObject::AXObjectVector&) const; + void AccessibilityChildrenFromAOMProperty(AOMRelationListProperty, + AXObject::AXObjectVector&) const; bool HasContentEditableAttributeSet() const; bool IsTextControl() const override; @@ -102,6 +102,7 @@ bool IsAnchor() const final; bool IsControl() const override; bool IsControllingVideoElement() const; + bool IsMultiline() const override; bool IsEditable() const override { return IsNativeTextControl(); } bool IsEmbeddedObject() const final; bool IsFieldset() const final;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp index 82bc2487..96c42953 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -392,6 +392,25 @@ return target ? target->element() : nullptr; } +bool AXObject::HasAOMProperty(AOMRelationListProperty property, + HeapVector<Member<Element>>& result) const { + Element* element = this->GetElement(); + if (!element) + return false; + + return AccessibleNode::GetProperty(element, property, result); +} + +bool AXObject::HasAOMPropertyOrARIAAttribute( + AOMRelationListProperty property, + HeapVector<Member<Element>>& result) const { + Element* element = this->GetElement(); + if (!element) + return false; + + return AccessibleNode::GetPropertyOrARIAAttribute(element, property, result); +} + bool AXObject::HasAOMPropertyOrARIAAttribute(AOMBooleanProperty property, bool& result) const { Element* element = this->GetElement(); @@ -520,7 +539,12 @@ if (!node) return kCheckedStateUndefined; - if (IsNativeInputInMixedState(node)) + // Expose native checkbox mixed state as accessibility mixed state. However, + // do not expose native radio mixed state as accessibility mixed state. + // This would confuse the JAWS screen reader, which reports a mixed radio as + // both checked and partially checked, but a native mixed native radio + // button sinply means no radio buttons have been checked in the group yet. + if (IsNativeCheckboxInMixedState(node)) return kCheckedStateMixed; if (isHTMLInputElement(*node) && @@ -532,14 +556,13 @@ return kCheckedStateFalse; } -bool AXObject::IsNativeInputInMixedState(const Node* node) { +bool AXObject::IsNativeCheckboxInMixedState(const Node* node) { if (!isHTMLInputElement(node)) return false; const HTMLInputElement* input = toHTMLInputElement(node); const auto inputType = input->type(); - if (inputType != InputTypeNames::checkbox && - inputType != InputTypeNames::radio) + if (inputType != InputTypeNames::checkbox) return false; return input->ShouldAppearIndeterminate(); } @@ -977,26 +1000,23 @@ // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. if (!in_aria_labelled_by_traversal && !already_visited) { - const QualifiedName& attr = - HasAttribute(aria_labeledbyAttr) && !HasAttribute(aria_labelledbyAttr) - ? aria_labeledbyAttr - : aria_labelledbyAttr; name_from = kAXNameFromRelatedElement; - if (name_sources) { - name_sources->push_back(NameSource(*found_text_alternative, attr)); - name_sources->back().type = name_from; - } - const AtomicString& aria_labelledby = GetAttribute(attr); - if (!aria_labelledby.IsNull()) { - if (name_sources) - name_sources->back().attribute_value = aria_labelledby; + // Check AOM property first. + HeapVector<Member<Element>> elements; + if (HasAOMProperty(AOMRelationListProperty::kLabeledBy, elements)) { + if (name_sources) { + name_sources->push_back( + NameSource(*found_text_alternative, aria_labelledbyAttr)); + name_sources->back().type = name_from; + } // Operate on a copy of |visited| so that if |nameSources| is not null, // the set of visited objects is preserved unmodified for future // calculations. AXObjectSet visited_copy = visited; - text_alternative = TextFromAriaLabelledby(visited_copy, related_objects); + text_alternative = + TextFromElements(true, visited_copy, elements, related_objects); if (!text_alternative.IsNull()) { if (name_sources) { NameSource& source = name_sources->back(); @@ -1011,6 +1031,44 @@ } else if (name_sources) { name_sources->back().invalid = true; } + } else { + // Now check ARIA attribute + const QualifiedName& attr = + HasAttribute(aria_labeledbyAttr) && !HasAttribute(aria_labelledbyAttr) + ? aria_labeledbyAttr + : aria_labelledbyAttr; + + if (name_sources) { + name_sources->push_back(NameSource(*found_text_alternative, attr)); + name_sources->back().type = name_from; + } + + const AtomicString& aria_labelledby = GetAttribute(attr); + if (!aria_labelledby.IsNull()) { + if (name_sources) + name_sources->back().attribute_value = aria_labelledby; + + // Operate on a copy of |visited| so that if |nameSources| is not null, + // the set of visited objects is preserved unmodified for future + // calculations. + AXObjectSet visited_copy = visited; + text_alternative = + TextFromAriaLabelledby(visited_copy, related_objects); + if (!text_alternative.IsNull()) { + if (name_sources) { + NameSource& source = name_sources->back(); + source.type = name_from; + source.related_objects = *related_objects; + source.text = text_alternative; + *found_text_alternative = true; + } else { + *found_text_alternative = true; + return text_alternative; + } + } else if (name_sources) { + name_sources->back().invalid = true; + } + } } } @@ -1162,24 +1220,6 @@ return AXDefaultActionVerb::kClick; } } - -bool AXObject::IsMultiline() const { - Node* node = this->GetNode(); - if (!node) - return false; - - if (isHTMLTextAreaElement(*node)) - return true; - - if (HasEditableStyle(*node)) - return true; - - if (!IsNativeTextControl() && !IsNonNativeTextControl()) - return false; - - return AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty::kMultiline); -} - bool AXObject::AriaPressedIsPresent() const { return !GetAttribute(aria_pressedAttr).IsEmpty(); }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h index ba79e1e..8e746a0 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -45,6 +45,7 @@ namespace blink { +class AccessibleNodeList; class AXObject; class AXObjectCacheImpl; class Element; @@ -60,6 +61,7 @@ enum class AOMIntProperty; enum class AOMFloatProperty; enum class AOMRelationProperty; +enum class AOMRelationListProperty; typedef unsigned AXID; @@ -354,6 +356,10 @@ // or the equivalent ARIA attribute, in that order. const AtomicString& GetAOMPropertyOrARIAAttribute(AOMStringProperty) const; Element* GetAOMPropertyOrARIAAttribute(AOMRelationProperty) const; + bool HasAOMProperty(AOMRelationListProperty, + HeapVector<Member<Element>>& result) const; + bool HasAOMPropertyOrARIAAttribute(AOMRelationListProperty, + HeapVector<Member<Element>>& result) const; bool HasAOMPropertyOrARIAAttribute(AOMBooleanProperty, bool& result) const; bool AOMPropertyOrARIAAttributeIsTrue(AOMBooleanProperty) const; bool AOMPropertyOrARIAAttributeIsFalse(AOMBooleanProperty) const; @@ -634,7 +640,7 @@ virtual void AriaLabelledbyElements(AXObjectVector&) const {} virtual bool AriaHasPopup() const { return false; } virtual bool IsEditable() const { return false; } - bool IsMultiline() const; + virtual bool IsMultiline() const { return false; } virtual bool IsRichlyEditable() const { return false; } bool AriaCheckedIsPresent() const; bool AriaPressedIsPresent() const; @@ -807,6 +813,8 @@ static AccessibilityRole AriaRoleToWebCoreRole(const String&); static const AtomicString& RoleName(AccessibilityRole); static const AtomicString& InternalRoleName(AccessibilityRole); + static void AccessibleNodeListToElementVector(const AccessibleNodeList&, + HeapVector<Member<Element>>&); protected: AXID id_; @@ -841,7 +849,6 @@ String TextFromAriaLabelledby(AXObjectSet& visited, AXRelatedObjectVector* related_objects) const; String TextFromAriaDescribedby(AXRelatedObjectVector* related_objects) const; - virtual const AXObject* InheritsPresentationalRoleFrom() const { return 0; } bool CanReceiveAccessibilityFocus() const; @@ -880,7 +887,7 @@ private: bool IsCheckable() const; - static bool IsNativeInputInMixedState(const Node*); + static bool IsNativeCheckboxInMixedState(const Node*); static bool IncludesARIAWidgetRole(const String&); static bool HasInteractiveARIAAttribute(const Element&);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp index a1ca9b9c..f94bfeb1 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp
@@ -12,7 +12,7 @@ namespace blink { -class AXObjectTest : public testing::Test { +class AXObjectTest : public ::testing::Test { protected: Document& GetDocument() { return page_holder_->GetDocument(); }
diff --git a/third_party/WebKit/Source/modules/budget/BudgetService.cpp b/third_party/WebKit/Source/modules/budget/BudgetService.cpp index 9b48bb3b..dcd83f8b 100644 --- a/third_party/WebKit/Source/modules/budget/BudgetService.cpp +++ b/third_party/WebKit/Source/modules/budget/BudgetService.cpp
@@ -11,9 +11,9 @@ #include "core/dom/ExecutionContext.h" #include "modules/budget/BudgetState.h" #include "platform/bindings/ScriptState.h" -#include "public/platform/InterfaceProvider.h" #include "public/platform/Platform.h" #include "public/platform/modules/budget_service/budget_service.mojom-blink.h" +#include "services/service_manager/public/cpp/interface_provider.h" namespace blink { namespace { @@ -43,9 +43,9 @@ } // namespace -BudgetService::BudgetService() { - Platform::Current()->GetInterfaceProvider()->GetInterface( - mojo::MakeRequest(&service_)); +BudgetService::BudgetService( + service_manager::InterfaceProvider* interface_provider) { + interface_provider->GetInterface(mojo::MakeRequest(&service_)); // Set a connection error handler, so that if an embedder doesn't // implement a BudgetSerice mojo service, the developer will get a
diff --git a/third_party/WebKit/Source/modules/budget/BudgetService.h b/third_party/WebKit/Source/modules/budget/BudgetService.h index 013a80e0..f366f70 100644 --- a/third_party/WebKit/Source/modules/budget/BudgetService.h +++ b/third_party/WebKit/Source/modules/budget/BudgetService.h
@@ -9,6 +9,10 @@ #include "platform/bindings/ScriptWrappable.h" #include "public/platform/modules/budget_service/budget_service.mojom-blink.h" +namespace service_manager { +class InterfaceProvider; +} + namespace blink { class ScriptPromise; @@ -23,7 +27,10 @@ DEFINE_WRAPPERTYPEINFO(); public: - static BudgetService* Create() { return new BudgetService(); } + static BudgetService* Create( + service_manager::InterfaceProvider* interface_provider) { + return new BudgetService(interface_provider); + } ~BudgetService(); @@ -48,7 +55,7 @@ // Error handler for use if mojo service doesn't connect. void OnConnectionError(); - BudgetService(); + explicit BudgetService(service_manager::InterfaceProvider*); // Pointer to the Mojo service which will proxy calls to the browser. mojom::blink::BudgetServicePtr service_;
diff --git a/third_party/WebKit/Source/modules/budget/DEPS b/third_party/WebKit/Source/modules/budget/DEPS new file mode 100644 index 0000000..5dbe03e --- /dev/null +++ b/third_party/WebKit/Source/modules/budget/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+services/service_manager/public/cpp", +]
diff --git a/third_party/WebKit/Source/modules/budget/NavigatorBudget.cpp b/third_party/WebKit/Source/modules/budget/NavigatorBudget.cpp index dc6eb4e7..98ab268 100644 --- a/third_party/WebKit/Source/modules/budget/NavigatorBudget.cpp +++ b/third_party/WebKit/Source/modules/budget/NavigatorBudget.cpp
@@ -4,6 +4,8 @@ #include "modules/budget/NavigatorBudget.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Navigator.h" #include "modules/budget/BudgetService.h" @@ -32,8 +34,13 @@ } BudgetService* NavigatorBudget::budget() { - if (!budget_) - budget_ = BudgetService::Create(); + if (!budget_) { + Navigator* navigator = GetSupplementable(); + if (navigator->GetFrame()) { + budget_ = BudgetService::Create( + navigator->GetFrame()->Client()->GetInterfaceProvider()); + } + } return budget_.Get(); }
diff --git a/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.cpp b/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.cpp index aa39cf3..af68d85e 100644 --- a/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.cpp +++ b/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.cpp
@@ -4,7 +4,9 @@ #include "modules/budget/WorkerNavigatorBudget.h" +#include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerNavigator.h" +#include "core/workers/WorkerThread.h" #include "modules/budget/BudgetService.h" namespace blink { @@ -33,16 +35,19 @@ return *worker_navigator_budget; } -BudgetService* WorkerNavigatorBudget::budget() { - if (!budget_) - budget_ = BudgetService::Create(); +BudgetService* WorkerNavigatorBudget::budget(ExecutionContext* context) { + if (!budget_) { + WorkerThread* thread = ToWorkerGlobalScope(context)->GetThread(); + budget_ = BudgetService::Create(&thread->GetInterfaceProvider()); + } return budget_.Get(); } // static BudgetService* WorkerNavigatorBudget::budget( + ExecutionContext* context, WorkerNavigator& worker_navigator) { - return WorkerNavigatorBudget::From(worker_navigator).budget(); + return WorkerNavigatorBudget::From(worker_navigator).budget(context); } DEFINE_TRACE(WorkerNavigatorBudget) {
diff --git a/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.h b/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.h index ccc12fd5..8f6cf1f 100644 --- a/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.h +++ b/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.h
@@ -13,6 +13,7 @@ namespace blink { class BudgetService; +class ExecutionContext; class WorkerNavigator; // This exposes the budget object on the WorkerNavigator partial interface. @@ -25,8 +26,8 @@ public: static WorkerNavigatorBudget& From(WorkerNavigator&); - static BudgetService* budget(WorkerNavigator&); - BudgetService* budget(); + static BudgetService* budget(ExecutionContext*, WorkerNavigator&); + BudgetService* budget(ExecutionContext*); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.idl b/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.idl index 9720c97..69d19b3 100644 --- a/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.idl +++ b/third_party/WebKit/Source/modules/budget/WorkerNavigatorBudget.idl
@@ -7,5 +7,5 @@ [ RuntimeEnabled=Budget ] partial interface WorkerNavigator { - [SameObject] readonly attribute BudgetService budget; + [SameObject, CallWith=ExecutionContext] readonly attribute BudgetService budget; };
diff --git a/third_party/WebKit/Source/modules/canvas/HTMLCanvasElementModule.cpp b/third_party/WebKit/Source/modules/canvas/HTMLCanvasElementModule.cpp index e619c76..00895460 100644 --- a/third_party/WebKit/Source/modules/canvas/HTMLCanvasElementModule.cpp +++ b/third_party/WebKit/Source/modules/canvas/HTMLCanvasElementModule.cpp
@@ -65,7 +65,7 @@ offscreen_canvas->SetPlaceholderCanvasId(canvas_id); canvas.RegisterPlaceholder(canvas_id); - CanvasSurfaceLayerBridge* bridge = canvas.SurfaceLayerBridge(); + SurfaceLayerBridge* bridge = canvas.SurfaceLayerBridge(); if (bridge) { offscreen_canvas->SetFrameSinkId(bridge->GetFrameSinkId().client_id(), bridge->GetFrameSinkId().sink_id());
diff --git a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainerTest.cpp b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainerTest.cpp index 91a7b9e..873b344 100644 --- a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainerTest.cpp +++ b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainerTest.cpp
@@ -50,7 +50,7 @@ // Set up. scope.GetDocument().SetSecurityOrigin( SecurityOrigin::CreateFromString("https://example.test")); - testing::StrictMock<MockCredentialManagerClient> mock_client; + ::testing::StrictMock<MockCredentialManagerClient> mock_client; ProvideCredentialManagerClientTo(scope.GetPage(), new CredentialManagerClient(&mock_client));
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp index 9035109..66d5748 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp +++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp
@@ -18,7 +18,7 @@ namespace blink { -class PaintWorkletTest : public testing::Test { +class PaintWorkletTest : public ::testing::Test { public: PaintWorkletTest() : page_(DummyPageHolder::Create()) {}
diff --git a/third_party/WebKit/Source/modules/geolocation/Geolocation.idl b/third_party/WebKit/Source/modules/geolocation/Geolocation.idl index 002276a..3e72608d 100644 --- a/third_party/WebKit/Source/modules/geolocation/Geolocation.idl +++ b/third_party/WebKit/Source/modules/geolocation/Geolocation.idl
@@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/geolocation-API/#geolocation_interface +// https://www.w3.org/TR/geolocation-API/#geolocation_interface [ NoInterfaceObject ] interface Geolocation {
diff --git a/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h b/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h index 971f62e..d5fd60e 100644 --- a/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h +++ b/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h
@@ -14,7 +14,7 @@ namespace blink { -class MockWebIDBDatabase : public testing::StrictMock<WebIDBDatabase> { +class MockWebIDBDatabase : public ::testing::StrictMock<WebIDBDatabase> { public: virtual ~MockWebIDBDatabase();
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestDetailsTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestDetailsTest.cpp index 3f821bc..df8dfef1 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequestDetailsTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequestDetailsTest.cpp
@@ -123,7 +123,7 @@ } class PaymentRequestDetailsTest - : public testing::TestWithParam<DetailsTestCase> {}; + : public ::testing::TestWithParam<DetailsTestCase> {}; TEST_P(PaymentRequestDetailsTest, ValidatesDetails) { V8TestingScope scope; @@ -145,738 +145,738 @@ INSTANTIATE_TEST_CASE_P( EmptyData, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataLabel, - kPaymentTestOverwriteValue, - "", - false), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataLabel, - kPaymentTestOverwriteValue, - "", - false), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataId, - kPaymentTestOverwriteValue, - "", - false), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataLabel, - kPaymentTestOverwriteValue, - "", - false), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataLabel, - kPaymentTestOverwriteValue, - "", - false), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataLabel, - kPaymentTestOverwriteValue, - "", - false))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataLabel, + kPaymentTestOverwriteValue, + "", + false), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataLabel, + kPaymentTestOverwriteValue, + "", + false), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataId, + kPaymentTestOverwriteValue, + "", + false), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataLabel, + kPaymentTestOverwriteValue, + "", + false), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataLabel, + kPaymentTestOverwriteValue, + "", + false), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataLabel, + kPaymentTestOverwriteValue, + "", + false))); INSTANTIATE_TEST_CASE_P( ValidCurrencyCodeFormat, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataCurrencyCode, - kPaymentTestOverwriteValue, - "USD"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataCurrencyCode, - kPaymentTestOverwriteValue, - "USD"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataCurrencyCode, - kPaymentTestOverwriteValue, - "USD"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataCurrencyCode, - kPaymentTestOverwriteValue, - "USD"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataCurrencyCode, - kPaymentTestOverwriteValue, - "USD"))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataCurrencyCode, + kPaymentTestOverwriteValue, + "USD"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataCurrencyCode, + kPaymentTestOverwriteValue, + "USD"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataCurrencyCode, + kPaymentTestOverwriteValue, + "USD"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataCurrencyCode, + kPaymentTestOverwriteValue, + "USD"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataCurrencyCode, + kPaymentTestOverwriteValue, + "USD"))); INSTANTIATE_TEST_CASE_P( ValidCurrencySystem, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataCurrencySystem, - kPaymentTestOverwriteValue, - "https://bitcoin.org"))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataCurrencySystem, + kPaymentTestOverwriteValue, + "https://bitcoin.org"))); INSTANTIATE_TEST_CASE_P( InvalidCurrencySystem, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataCurrencySystem, - kPaymentTestOverwriteValue, - "\\^%\\", - true, - kV8TypeError))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataCurrencySystem, + kPaymentTestOverwriteValue, + "\\^%\\", + true, + kV8TypeError))); INSTANTIATE_TEST_CASE_P( ValidValueFormat, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "0"), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1"), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10"), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.99"), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "012345678901234567890123456789"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "0"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-0"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.99"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3.00"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "012345678901234567890123456789"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-012345678901234567890123456789"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "0"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-0"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.99"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3.00"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "012345678901234567890123456789"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-012345678901234567890123456789"))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "0"), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1"), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10"), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.99"), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "012345678901234567890123456789"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "0"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-0"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.99"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3.00"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "012345678901234567890123456789"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-012345678901234567890123456789"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "0"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-0"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.99"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3.00"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "012345678901234567890123456789"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-012345678901234567890123456789"))); INSTANTIATE_TEST_CASE_P( ValidValueFormatForModifier, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "0"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.99"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "012345678901234567890123456789"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "0"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-0"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.99"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3.00"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "012345678901234567890123456789"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789.0123456789"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789012345678.9"), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-012345678901234567890123456789"))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "0"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.99"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "012345678901234567890123456789"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "0"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-0"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.99"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3.00"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "012345678901234567890123456789"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789.0123456789"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789012345678.9"), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-012345678901234567890123456789"))); INSTANTIATE_TEST_CASE_P( InvalidValueFormat, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3.00", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "notdigits", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "ALSONOTDIGITS", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - ".99", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1.0.0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1/3", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789.0123456789", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789012345678.9", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-012345678901234567890123456789", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "notdigits", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "ALSONOTDIGITS", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - ".99", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1.0.0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1/3", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "notdigits", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "ALSONOTDIGITS", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - ".99", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1.0.0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailShippingOption, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1/3", - true, - kV8TypeError))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3.00", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "notdigits", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "ALSONOTDIGITS", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + ".99", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1.0.0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1/3", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789.0123456789", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789012345678.9", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-012345678901234567890123456789", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "notdigits", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "ALSONOTDIGITS", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + ".99", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1.0.0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1/3", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "notdigits", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "ALSONOTDIGITS", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + ".99", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1.0.0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailShippingOption, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1/3", + true, + kV8TypeError))); INSTANTIATE_TEST_CASE_P( InvalidValueFormatForModifier, PaymentRequestDetailsTest, - testing::Values(DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-3.00", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "notdigits", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "ALSONOTDIGITS", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - ".99", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1.0.0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1/3", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789.0123456789", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-01234567890123456789012345678.9", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierTotal, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-012345678901234567890123456789", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "notdigits", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "ALSONOTDIGITS", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - ".99", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "-10.", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "10-", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1-0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1.0.0", - true, - kV8TypeError), - DetailsTestCase(kPaymentTestDetailModifierItem, - kPaymentTestDataValue, - kPaymentTestOverwriteValue, - "1/3", - true, - kV8TypeError))); + ::testing::Values(DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-3.00", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "notdigits", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "ALSONOTDIGITS", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + ".99", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1.0.0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1/3", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789.0123456789", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-01234567890123456789012345678.9", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierTotal, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-012345678901234567890123456789", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "notdigits", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "ALSONOTDIGITS", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + ".99", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "-10.", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "10-", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1-0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1.0.0", + true, + kV8TypeError), + DetailsTestCase(kPaymentTestDetailModifierItem, + kPaymentTestDataValue, + kPaymentTestOverwriteValue, + "1/3", + true, + kV8TypeError))); } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp index 6f6c387..f65812d 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp
@@ -48,8 +48,8 @@ scope.GetExceptionState()); EXPECT_FALSE(scope.GetExceptionState().HadException()); - EXPECT_CALL(*updater, OnUpdatePaymentDetails(testing::_)); - EXPECT_CALL(*updater, OnUpdatePaymentDetailsFailure(testing::_)).Times(0); + EXPECT_CALL(*updater, OnUpdatePaymentDetails(::testing::_)); + EXPECT_CALL(*updater, OnUpdatePaymentDetailsFailure(::testing::_)).Times(0); payment_details->Resolve("foo"); } @@ -67,8 +67,8 @@ scope.GetExceptionState()); EXPECT_FALSE(scope.GetExceptionState().HadException()); - EXPECT_CALL(*updater, OnUpdatePaymentDetails(testing::_)).Times(0); - EXPECT_CALL(*updater, OnUpdatePaymentDetailsFailure(testing::_)); + EXPECT_CALL(*updater, OnUpdatePaymentDetails(::testing::_)).Times(0); + EXPECT_CALL(*updater, OnUpdatePaymentDetailsFailure(::testing::_)); payment_details->Reject("oops"); }
diff --git a/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp index 7c34ada9..757b9cb 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp
@@ -28,8 +28,8 @@ public: MockPaymentCompleter() { - ON_CALL(*this, Complete(testing::_, testing::_)) - .WillByDefault(testing::ReturnPointee(&dummy_promise_)); + ON_CALL(*this, Complete(::testing::_, ::testing::_)) + .WillByDefault(::testing::ReturnPointee(&dummy_promise_)); } ~MockPaymentCompleter() override {}
diff --git a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp index a2a53ee..f8a788ad 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
@@ -213,26 +213,26 @@ PaymentRequestMockFunctionScope::~PaymentRequestMockFunctionScope() { v8::MicrotasksScope::PerformCheckpoint(script_state_->GetIsolate()); for (MockFunction* mock_function : mock_functions_) { - testing::Mock::VerifyAndClearExpectations(mock_function); + ::testing::Mock::VerifyAndClearExpectations(mock_function); } } v8::Local<v8::Function> PaymentRequestMockFunctionScope::ExpectCall( String* captor) { mock_functions_.push_back(new MockFunction(script_state_, captor)); - EXPECT_CALL(*mock_functions_.back(), Call(testing::_)); + EXPECT_CALL(*mock_functions_.back(), Call(::testing::_)); return mock_functions_.back()->Bind(); } v8::Local<v8::Function> PaymentRequestMockFunctionScope::ExpectCall() { mock_functions_.push_back(new MockFunction(script_state_)); - EXPECT_CALL(*mock_functions_.back(), Call(testing::_)); + EXPECT_CALL(*mock_functions_.back(), Call(::testing::_)); return mock_functions_.back()->Bind(); } v8::Local<v8::Function> PaymentRequestMockFunctionScope::ExpectNoCall() { mock_functions_.push_back(new MockFunction(script_state_)); - EXPECT_CALL(*mock_functions_.back(), Call(testing::_)).Times(0); + EXPECT_CALL(*mock_functions_.back(), Call(::testing::_)).Times(0); return mock_functions_.back()->Bind(); } @@ -245,16 +245,16 @@ PaymentRequestMockFunctionScope::MockFunction::MockFunction( ScriptState* script_state) : ScriptFunction(script_state) { - ON_CALL(*this, Call(testing::_)).WillByDefault(testing::ReturnArg<0>()); + ON_CALL(*this, Call(::testing::_)).WillByDefault(::testing::ReturnArg<0>()); } PaymentRequestMockFunctionScope::MockFunction::MockFunction( ScriptState* script_state, String* captor) : ScriptFunction(script_state), value_(captor) { - ON_CALL(*this, Call(testing::_)) + ON_CALL(*this, Call(::testing::_)) .WillByDefault( - testing::DoAll(SaveValueIn(value_), testing::ReturnArg<0>())); + ::testing::DoAll(SaveValueIn(value_), ::testing::ReturnArg<0>())); } v8::Local<v8::Function> PaymentRequestMockFunctionScope::MockFunction::Bind() {
diff --git a/third_party/WebKit/Source/modules/payments/PaymentsValidatorsTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentsValidatorsTest.cpp index 6b59fada..6a7e110 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentsValidatorsTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentsValidatorsTest.cpp
@@ -24,7 +24,7 @@ }; class PaymentsCurrencyValidatorTest - : public testing::TestWithParam<CurrencyCodeTestCase> {}; + : public ::testing::TestWithParam<CurrencyCodeTestCase> {}; const char* LongString2048() { static char long_string[2049]; @@ -59,7 +59,7 @@ INSTANTIATE_TEST_CASE_P( CurrencyCodes, PaymentsCurrencyValidatorTest, - testing::Values( + ::testing::Values( // The most common identifiers are three-letter alphabetic codes as // defined by [ISO4217] (for example, "USD" for US Dollars). // |system| is a URL that indicates the currency system that the @@ -102,7 +102,8 @@ return out; } -class PaymentsAmountValidatorTest : public testing::TestWithParam<TestCase> {}; +class PaymentsAmountValidatorTest : public ::testing::TestWithParam<TestCase> { +}; TEST_P(PaymentsAmountValidatorTest, IsValidAmountFormat) { String error_message; @@ -121,34 +122,35 @@ INSTANTIATE_TEST_CASE_P( Amounts, PaymentsAmountValidatorTest, - testing::Values(TestCase("0", true), - TestCase("-0", true), - TestCase("1", true), - TestCase("10", true), - TestCase("-3", true), - TestCase("10.99", true), - TestCase("-3.00", true), - TestCase("01234567890123456789.0123456789", true), - TestCase("01234567890123456789012345678.9", true), - TestCase("012345678901234567890123456789", true), - TestCase("-01234567890123456789.0123456789", true), - TestCase("-01234567890123456789012345678.9", true), - TestCase("-012345678901234567890123456789", true), - // Invalid amount formats - TestCase("", false), - TestCase("-", false), - TestCase("notdigits", false), - TestCase("ALSONOTDIGITS", false), - TestCase("10.", false), - TestCase(".99", false), - TestCase("-10.", false), - TestCase("-.99", false), - TestCase("10-", false), - TestCase("1-0", false), - TestCase("1.0.0", false), - TestCase("1/3", false))); + ::testing::Values(TestCase("0", true), + TestCase("-0", true), + TestCase("1", true), + TestCase("10", true), + TestCase("-3", true), + TestCase("10.99", true), + TestCase("-3.00", true), + TestCase("01234567890123456789.0123456789", true), + TestCase("01234567890123456789012345678.9", true), + TestCase("012345678901234567890123456789", true), + TestCase("-01234567890123456789.0123456789", true), + TestCase("-01234567890123456789012345678.9", true), + TestCase("-012345678901234567890123456789", true), + // Invalid amount formats + TestCase("", false), + TestCase("-", false), + TestCase("notdigits", false), + TestCase("ALSONOTDIGITS", false), + TestCase("10.", false), + TestCase(".99", false), + TestCase("-10.", false), + TestCase("-.99", false), + TestCase("10-", false), + TestCase("1-0", false), + TestCase("1.0.0", false), + TestCase("1/3", false))); -class PaymentsRegionValidatorTest : public testing::TestWithParam<TestCase> {}; +class PaymentsRegionValidatorTest : public ::testing::TestWithParam<TestCase> { +}; TEST_P(PaymentsRegionValidatorTest, IsValidCountryCodeFormat) { String error_message; @@ -166,16 +168,16 @@ INSTANTIATE_TEST_CASE_P(CountryCodes, PaymentsRegionValidatorTest, - testing::Values(TestCase("US", true), - // Invalid country code formats - TestCase("U1", false), - TestCase("U", false), - TestCase("us", false), - TestCase("USA", false), - TestCase("", false))); + ::testing::Values(TestCase("US", true), + // Invalid country code formats + TestCase("U1", false), + TestCase("U", false), + TestCase("us", false), + TestCase("USA", false), + TestCase("", false))); -class PaymentsLanguageValidatorTest : public testing::TestWithParam<TestCase> { -}; +class PaymentsLanguageValidatorTest + : public ::testing::TestWithParam<TestCase> {}; TEST_P(PaymentsLanguageValidatorTest, IsValidLanguageCodeFormat) { String error_message; @@ -193,17 +195,18 @@ INSTANTIATE_TEST_CASE_P(LanguageCodes, PaymentsLanguageValidatorTest, - testing::Values(TestCase("", true), - TestCase("en", true), - TestCase("eng", true), - // Invalid language code formats - TestCase("e1", false), - TestCase("en1", false), - TestCase("e", false), - TestCase("engl", false), - TestCase("EN", false))); + ::testing::Values(TestCase("", true), + TestCase("en", true), + TestCase("eng", true), + // Invalid language code formats + TestCase("e1", false), + TestCase("en1", false), + TestCase("e", false), + TestCase("engl", false), + TestCase("EN", false))); -class PaymentsScriptValidatorTest : public testing::TestWithParam<TestCase> {}; +class PaymentsScriptValidatorTest : public ::testing::TestWithParam<TestCase> { +}; TEST_P(PaymentsScriptValidatorTest, IsValidScriptCodeFormat) { String error_message; @@ -221,15 +224,15 @@ INSTANTIATE_TEST_CASE_P(ScriptCodes, PaymentsScriptValidatorTest, - testing::Values(TestCase("", true), - TestCase("Latn", true), - // Invalid script code formats - TestCase("Lat1", false), - TestCase("1lat", false), - TestCase("Latin", false), - TestCase("Lat", false), - TestCase("latn", false), - TestCase("LATN", false))); + ::testing::Values(TestCase("", true), + TestCase("Latn", true), + // Invalid script code formats + TestCase("Lat1", false), + TestCase("1lat", false), + TestCase("Latin", false), + TestCase("Lat", false), + TestCase("latn", false), + TestCase("LATN", false))); struct ShippingAddressTestCase { ShippingAddressTestCase(const char* country_code, @@ -249,7 +252,7 @@ }; class PaymentsShippingAddressValidatorTest - : public testing::TestWithParam<ShippingAddressTestCase> {}; + : public ::testing::TestWithParam<ShippingAddressTestCase> {}; TEST_P(PaymentsShippingAddressValidatorTest, IsValidShippingAddress) { payments::mojom::blink::PaymentAddressPtr address = @@ -272,7 +275,7 @@ INSTANTIATE_TEST_CASE_P( ShippingAddresses, PaymentsShippingAddressValidatorTest, - testing::Values( + ::testing::Values( ShippingAddressTestCase("US", "en", "Latn", true), ShippingAddressTestCase("US", "en", "", true), ShippingAddressTestCase("US", "", "", true),
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp b/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp index 8510138a..97a18f4 100644 --- a/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp +++ b/third_party/WebKit/Source/modules/permissions/PermissionUtils.cpp
@@ -15,7 +15,9 @@ namespace blink { -using mojom::blink::PermissionDescriptor; +// There are two PermissionDescriptor, one in Mojo bindings and one +// in v8 bindings so we'll rename one here. +using MojoPermissionDescriptor = mojom::blink::PermissionDescriptor; using mojom::blink::PermissionDescriptorPtr; using mojom::blink::PermissionName; @@ -37,7 +39,7 @@ } PermissionDescriptorPtr CreatePermissionDescriptor(PermissionName name) { - auto descriptor = PermissionDescriptor::New(); + auto descriptor = MojoPermissionDescriptor::New(); descriptor->name = name; return descriptor; }
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp index 17d4c8cd..3abfda6e 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp
@@ -71,7 +71,7 @@ auto event_handler = new StrictMock<MockEventListener>(); AddConnectionavailableEventListener(event_handler, receiver); - EXPECT_CALL(*event_handler, handleEvent(testing::_, testing::_)).Times(0); + EXPECT_CALL(*event_handler, handleEvent(::testing::_, ::testing::_)).Times(0); receiver->connectionList(scope.GetScriptState()); @@ -86,7 +86,7 @@ auto event_handler = new StrictMock<MockEventListener>(); AddConnectionavailableEventListener(event_handler, receiver); - EXPECT_CALL(*event_handler, handleEvent(testing::_, testing::_)).Times(0); + EXPECT_CALL(*event_handler, handleEvent(::testing::_, ::testing::_)).Times(0); receiver->connectionList(scope.GetScriptState()); @@ -106,7 +106,7 @@ StrictMock<MockEventListener>* event_handler = new StrictMock<MockEventListener>(); AddConnectionavailableEventListener(event_handler, receiver); - EXPECT_CALL(*event_handler, handleEvent(testing::_, testing::_)).Times(1); + EXPECT_CALL(*event_handler, handleEvent(::testing::_, ::testing::_)).Times(1); receiver->connectionList(scope.GetScriptState()); @@ -127,7 +127,7 @@ StrictMock<MockEventListener>* event_handler = new StrictMock<MockEventListener>(); AddConnectionavailableEventListener(event_handler, receiver); - EXPECT_CALL(*event_handler, handleEvent(testing::_, testing::_)).Times(0); + EXPECT_CALL(*event_handler, handleEvent(::testing::_, ::testing::_)).Times(0); WebPresentationInfo presentation_info(KURL(NullURL(), "http://example.com"), "id"); @@ -149,7 +149,7 @@ TEST_F(PresentationReceiverTest, CreateReceiver) { MockWebPresentationClient client; - EXPECT_CALL(client, SetReceiver(testing::_)); + EXPECT_CALL(client, SetReceiver(::testing::_)); V8TestingScope scope; new PresentationReceiver(&scope.GetFrame(), &client);
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp index b4fc3cf..f0c6c9f 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp
@@ -733,9 +733,9 @@ INSTANTIATE_TEST_CASE_P( BaseAudioContextAutoplayTest, BaseAudioContextAutoplayTest, - testing::Values(AutoplayPolicy::Type::kNoUserGestureRequired, - AutoplayPolicy::Type::kUserGestureRequired, - AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin, - AutoplayPolicy::Type::kDocumentUserActivationRequired)); + ::testing::Values(AutoplayPolicy::Type::kNoUserGestureRequired, + AutoplayPolicy::Type::kUserGestureRequired, + AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin, + AutoplayPolicy::Type::kDocumentUserActivationRequired)); } // namespace blink
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp index 9a28f76..0e1df756 100644 --- a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp +++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
@@ -26,23 +26,23 @@ #include "testing/gtest/include/gtest/gtest.h" #include "v8/include/v8.h" -using testing::_; -using testing::AnyNumber; -using testing::InSequence; -using testing::Ref; -using testing::Return; +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::InSequence; +using ::testing::Ref; +using ::testing::Return; namespace blink { namespace { -typedef testing::StrictMock<testing::MockFunction<void(int)>> +typedef ::testing::StrictMock<::testing::MockFunction<void(int)>> Checkpoint; // NOLINT class MockWebSocketChannel : public WebSocketChannel { public: static MockWebSocketChannel* Create() { - return new testing::StrictMock<MockWebSocketChannel>(); + return new ::testing::StrictMock<MockWebSocketChannel>(); } ~MockWebSocketChannel() override {}
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp index bdcb50b..d83766d1 100644 --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
@@ -26,17 +26,17 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; -using testing::InSequence; -using testing::PrintToString; -using testing::AnyNumber; -using testing::SaveArg; +using ::testing::_; +using ::testing::InSequence; +using ::testing::PrintToString; +using ::testing::AnyNumber; +using ::testing::SaveArg; namespace blink { namespace { -typedef testing::StrictMock<testing::MockFunction<void(int)>> Checkpoint; +typedef ::testing::StrictMock<::testing::MockFunction<void(int)>> Checkpoint; class MockWebSocketChannelClient : public GarbageCollectedFinalized<MockWebSocketChannelClient>, @@ -45,7 +45,7 @@ public: static MockWebSocketChannelClient* Create() { - return new testing::StrictMock<MockWebSocketChannelClient>(); + return new ::testing::StrictMock<MockWebSocketChannelClient>(); } MockWebSocketChannelClient() {} @@ -72,7 +72,7 @@ class MockWebSocketHandle : public WebSocketHandle { public: static MockWebSocketHandle* Create() { - return new testing::StrictMock<MockWebSocketHandle>(); + return new ::testing::StrictMock<MockWebSocketHandle>(); } MockWebSocketHandle() {} @@ -100,7 +100,7 @@ class MockWebSocketHandshakeThrottle : public WebSocketHandshakeThrottle { public: static MockWebSocketHandshakeThrottle* Create() { - return new testing::StrictMock<MockWebSocketHandshakeThrottle>(); + return new ::testing::StrictMock<MockWebSocketHandshakeThrottle>(); } MockWebSocketHandshakeThrottle() {} ~MockWebSocketHandshakeThrottle() override { Destructor(); }
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 79c3117..93a78d7 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -627,6 +627,7 @@ "exported/WebSpeechSynthesizerClientImpl.h", "exported/WebStorageQuotaCallbacks.cpp", "exported/WebString.cpp", + "exported/WebSurfaceLayerBridge.cpp", "exported/WebTextRun.cpp", "exported/WebThreadSafeData.cpp", "exported/WebURL.cpp", @@ -835,8 +836,6 @@ "graphics/CanvasHeuristicParameters.h", "graphics/CanvasMetrics.cpp", "graphics/CanvasMetrics.h", - "graphics/CanvasSurfaceLayerBridge.cpp", - "graphics/CanvasSurfaceLayerBridge.h", "graphics/Color.cpp", "graphics/Color.h", "graphics/ColorBehavior.cpp", @@ -958,6 +957,8 @@ "graphics/StaticBitmapImage.h", "graphics/StrokeData.cpp", "graphics/StrokeData.h", + "graphics/SurfaceLayerBridge.cpp", + "graphics/SurfaceLayerBridge.h", "graphics/TextureHolder.h", "graphics/TouchAction.h", "graphics/UnacceleratedImageBufferSurface.cpp",
diff --git a/third_party/WebKit/Source/platform/Language.cpp b/third_party/WebKit/Source/platform/Language.cpp index 25cb415..12fff45 100644 --- a/third_party/WebKit/Source/platform/Language.cpp +++ b/third_party/WebKit/Source/platform/Language.cpp
@@ -25,6 +25,7 @@ #include "platform/Language.h" +#include "platform/text/PlatformLocale.h" #include "platform/wtf/text/WTFString.h" #include "public/platform/Platform.h" @@ -89,6 +90,7 @@ canonicalized.ReserveCapacity(override.size()); for (const auto& lang : override) canonicalized.push_back(CanonicalizeLanguageIdentifier(lang)); + Locale::ResetDefautlLocale(); } AtomicString DefaultLanguage() {
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.cpp b/third_party/WebKit/Source/platform/LayoutLocale.cpp index 309e06b9..65161299 100644 --- a/third_party/WebKit/Source/platform/LayoutLocale.cpp +++ b/third_party/WebKit/Source/platform/LayoutLocale.cpp
@@ -6,6 +6,7 @@ #include "platform/Language.h" #include "platform/fonts/AcceptLanguagesResolver.h" +#include "platform/fonts/FontGlobalContext.h" #include "platform/text/ICUError.h" #include "platform/text/LocaleToScriptMapping.h" #include "platform/wtf/HashMap.h" @@ -17,11 +18,6 @@ namespace blink { -const LayoutLocale* LayoutLocale::default_ = nullptr; -const LayoutLocale* LayoutLocale::system_ = nullptr; -const LayoutLocale* LayoutLocale::default_for_han_ = nullptr; -bool LayoutLocale::default_for_han_computed_ = false; - static hb_language_t ToHarfbuzLanguage(const AtomicString& locale) { CString locale_as_latin1 = locale.Latin1(); return hb_language_from_string(locale_as_latin1.data(), @@ -85,21 +81,21 @@ const LayoutLocale* content_locale) { if (content_locale && content_locale->HasScriptForHan()) return content_locale; - if (!default_for_han_computed_) - ComputeLocaleForHan(); - return default_for_han_; -} -void LayoutLocale::ComputeLocaleForHan() { + if (FontGlobalContext::HasDefaultLocaleForHan()) + return FontGlobalContext::GetDefaultLocaleForHan(); + + const LayoutLocale* default_for_han; if (const LayoutLocale* locale = AcceptLanguagesResolver::LocaleForHan()) - default_for_han_ = locale; + default_for_han = locale; else if (GetDefault().HasScriptForHan()) - default_for_han_ = &GetDefault(); + default_for_han = &GetDefault(); else if (GetSystem().HasScriptForHan()) - default_for_han_ = &GetSystem(); + default_for_han = &GetSystem(); else - default_for_han_ = nullptr; - default_for_han_computed_ = true; + default_for_han = nullptr; + FontGlobalContext::SetDefaultLocaleForHan(default_for_han); + return default_for_han; } const char* LayoutLocale::LocaleForHanForSkFontMgr() const { @@ -116,42 +112,38 @@ has_script_for_han_(false), hyphenation_computed_(false) {} -using LayoutLocaleMap = - HashMap<AtomicString, RefPtr<LayoutLocale>, CaseFoldingHash>; - -static LayoutLocaleMap& GetLocaleMap() { - DEFINE_STATIC_LOCAL(LayoutLocaleMap, locale_map, ()); - return locale_map; -} - const LayoutLocale* LayoutLocale::Get(const AtomicString& locale) { if (locale.IsNull()) return nullptr; - auto result = GetLocaleMap().insert(locale, nullptr); + auto result = FontGlobalContext::GetLayoutLocaleMap().insert(locale, nullptr); if (result.is_new_entry) result.stored_value->value = AdoptRef(new LayoutLocale(locale)); return result.stored_value->value.Get(); } const LayoutLocale& LayoutLocale::GetDefault() { - if (default_) - return *default_; + if (const LayoutLocale* locale = FontGlobalContext::GetDefaultLayoutLocale()) + return *locale; - AtomicString locale = DefaultLanguage(); - default_ = Get(!locale.IsEmpty() ? locale : "en"); - return *default_; + AtomicString language = DefaultLanguage(); + const LayoutLocale* locale = + LayoutLocale::Get(!language.IsEmpty() ? language : "en"); + FontGlobalContext::SetDefaultLayoutLocale(locale); + return *locale; } const LayoutLocale& LayoutLocale::GetSystem() { - if (system_) - return *system_; + if (const LayoutLocale* locale = FontGlobalContext::GetSystemLayoutLocale()) + return *locale; // Platforms such as Windows can give more information than the default // locale, such as "en-JP" for English speakers in Japan. String name = icu::Locale::getDefault().getName(); - system_ = Get(AtomicString(name.Replace('_', '-'))); - return *system_; + const LayoutLocale* locale = + LayoutLocale::Get(AtomicString(name.Replace('_', '-'))); + FontGlobalContext::SetSystemLayoutLocale(locale); + return *locale; } PassRefPtr<LayoutLocale> LayoutLocale::CreateForTesting( @@ -159,14 +151,6 @@ return AdoptRef(new LayoutLocale(locale)); } -void LayoutLocale::ClearForTesting() { - default_ = nullptr; - system_ = nullptr; - default_for_han_ = nullptr; - default_for_han_computed_ = false; - GetLocaleMap().clear(); -} - Hyphenation* LayoutLocale::GetHyphenation() const { if (hyphenation_computed_) return hyphenation_.Get();
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.h b/third_party/WebKit/Source/platform/LayoutLocale.h index a2291cb7..e22bb9d 100644 --- a/third_party/WebKit/Source/platform/LayoutLocale.h +++ b/third_party/WebKit/Source/platform/LayoutLocale.h
@@ -54,7 +54,6 @@ UScriptCode GetScriptForHan() const; bool HasScriptForHan() const; static const LayoutLocale* LocaleForHan(const LayoutLocale*); - static void InvalidateLocaleForHan() { default_for_han_computed_ = false; } const char* LocaleForHanForSkFontMgr() const; Hyphenation* GetHyphenation() const; @@ -62,7 +61,6 @@ AtomicString LocaleWithBreakKeyword(LineBreakIteratorMode) const; static PassRefPtr<LayoutLocale> CreateForTesting(const AtomicString&); - static void ClearForTesting(); static void SetHyphenationForTesting(const AtomicString&, PassRefPtr<Hyphenation>); @@ -70,7 +68,6 @@ explicit LayoutLocale(const AtomicString&); void ComputeScriptForHan() const; - static void ComputeLocaleForHan(); AtomicString string_; mutable CString string_for_sk_font_mgr_; @@ -84,11 +81,6 @@ mutable unsigned has_script_for_han_ : 1; mutable unsigned hyphenation_computed_ : 1; - - static const LayoutLocale* default_; - static const LayoutLocale* system_; - static const LayoutLocale* default_for_han_; - static bool default_for_han_computed_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp b/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp index 853147a..b2ddf65 100644 --- a/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp +++ b/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
@@ -4,12 +4,13 @@ #include "platform/LayoutLocale.h" +#include "platform/fonts/FontGlobalContext.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink { TEST(LayoutLocaleTest, Get) { - LayoutLocale::ClearForTesting(); + FontGlobalContext::ClearForTesting(); EXPECT_EQ(nullptr, LayoutLocale::Get(g_null_atom)); @@ -20,7 +21,7 @@ EXPECT_STRCASEEQ("ja-jp", LayoutLocale::Get("ja-jp")->LocaleString().Ascii().data()); - LayoutLocale::ClearForTesting(); + FontGlobalContext::ClearForTesting(); } TEST(LayoutLocaleTest, GetCaseInsensitive) {
diff --git a/third_party/WebKit/Source/platform/PODArenaTest.cpp b/third_party/WebKit/Source/platform/PODArenaTest.cpp index 4b45df2..2e4359b 100644 --- a/third_party/WebKit/Source/platform/PODArenaTest.cpp +++ b/third_party/WebKit/Source/platform/PODArenaTest.cpp
@@ -51,7 +51,7 @@ } // anonymous namespace -class PODArenaTest : public testing::Test {}; +class PODArenaTest : public ::testing::Test {}; // Make sure the arena can successfully allocate from more than one // region.
diff --git a/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp b/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp index b2c9828..f5b2a26 100644 --- a/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp +++ b/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp
@@ -54,7 +54,7 @@ } // anonymous namespace -class PODFreeListArenaTest : public testing::Test { +class PODFreeListArenaTest : public ::testing::Test { protected: int GetFreeListSize(PassRefPtr<PODFreeListArena<TestClass1>> arena) const { return arena->GetFreeListSizeForTesting();
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp index 2b648f74..b3cf96a9 100644 --- a/third_party/WebKit/Source/platform/TimerTest.cpp +++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -21,12 +21,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::ElementsAre; +using ::testing::ElementsAre; namespace blink { namespace { -class TimerTest : public testing::Test { +class TimerTest : public ::testing::Test { public: void SetUp() override { run_times_.clear();
diff --git a/third_party/WebKit/Source/platform/WebIconSizesParserTest.cpp b/third_party/WebKit/Source/platform/WebIconSizesParserTest.cpp index e2eef2c8..74d2535b 100644 --- a/third_party/WebKit/Source/platform/WebIconSizesParserTest.cpp +++ b/third_party/WebKit/Source/platform/WebIconSizesParserTest.cpp
@@ -11,7 +11,7 @@ namespace blink { -class WebIconSizesParserTest : public testing::Test {}; +class WebIconSizesParserTest : public ::testing::Test {}; TEST(WebIconSizesParserTest, parseSizes) { WebString sizes_attribute = "32x33";
diff --git a/third_party/WebKit/Source/platform/bindings/RuntimeCallStatsTest.cpp b/third_party/WebKit/Source/platform/bindings/RuntimeCallStatsTest.cpp index 08270a6..edbf206 100644 --- a/third_party/WebKit/Source/platform/bindings/RuntimeCallStatsTest.cpp +++ b/third_party/WebKit/Source/platform/bindings/RuntimeCallStatsTest.cpp
@@ -25,7 +25,7 @@ } // namespace -class RuntimeCallStatsTest : public testing::Test { +class RuntimeCallStatsTest : public ::testing::Test { public: void SetUp() override { // Add one millisecond because RuntimeCallTimer uses |start_ticks_| =
diff --git a/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp b/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp index 1a5a7b0..75d53a7 100644 --- a/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp +++ b/third_party/WebKit/Source/platform/blob/BlobBytesProviderTest.cpp
@@ -12,7 +12,7 @@ namespace blink { namespace { -class BlobBytesProviderTest : public testing::Test { +class BlobBytesProviderTest : public ::testing::Test { public: void SetUp() override { test_bytes1_.resize(128); @@ -78,7 +78,7 @@ } class RequestAsFile : public BlobBytesProviderTest, - public testing::WithParamInterface<FileTestData> { + public ::testing::WithParamInterface<FileTestData> { public: void SetUp() override { BlobBytesProviderTest::SetUp(); @@ -209,7 +209,7 @@ INSTANTIATE_TEST_CASE_P(BlobBytesProviderTest, RequestAsFile, - testing::ValuesIn(file_tests)); + ::testing::ValuesIn(file_tests)); TEST_F(BlobBytesProviderTest, RequestAsFile_MultipleChunks) { auto provider = WTF::MakeUnique<BlobBytesProvider>(test_data1_);
diff --git a/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp b/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp index 5c37d41..74e6df3 100644 --- a/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp +++ b/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp
@@ -190,7 +190,7 @@ } // namespace -class BlobDataHandleTest : public testing::Test { +class BlobDataHandleTest : public ::testing::Test { public: BlobDataHandleTest() : enable_mojo_blobs_(true), testing_platform_(&mock_blob_registry_) {}
diff --git a/third_party/WebKit/Source/platform/exported/WebSurfaceLayerBridge.cpp b/third_party/WebKit/Source/platform/exported/WebSurfaceLayerBridge.cpp new file mode 100644 index 0000000..118628e --- /dev/null +++ b/third_party/WebKit/Source/platform/exported/WebSurfaceLayerBridge.cpp
@@ -0,0 +1,15 @@ +// 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/WebSurfaceLayerBridge.h" + +#include "third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.h" + +namespace blink { + +WebSurfaceLayerBridge* WebSurfaceLayerBridge::Create() { + return new SurfaceLayerBridge(nullptr, nullptr); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp index 5ca7a21..031e8f3f 100644 --- a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp +++ b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp
@@ -5,6 +5,7 @@ #include "platform/fonts/AcceptLanguagesResolver.h" #include "platform/LayoutLocale.h" +#include "platform/fonts/FontGlobalContext.h" namespace blink { @@ -20,7 +21,7 @@ return; current_value = accept_languages; - LayoutLocale::InvalidateLocaleForHan(); + FontGlobalContext::InvalidateLocaleForHan(); } const LayoutLocale* AcceptLanguagesResolver::LocaleForHan() {
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp index 2e0a775..2e5ebc8 100644 --- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp +++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -405,8 +405,10 @@ font_platform_data_cache_.clear(); generation_++; - for (const auto& client : *font_cache_clients_) - client->FontCacheInvalidated(); + if (font_cache_clients_) { + for (const auto& client : *font_cache_clients_) + client->FontCacheInvalidated(); + } Purge(kForcePurge); }
diff --git a/third_party/WebKit/Source/platform/fonts/FontGlobalContext.cpp b/third_party/WebKit/Source/platform/fonts/FontGlobalContext.cpp index 36f39ae..d2981cf 100644 --- a/third_party/WebKit/Source/platform/fonts/FontGlobalContext.cpp +++ b/third_party/WebKit/Source/platform/fonts/FontGlobalContext.cpp
@@ -19,7 +19,12 @@ return *font_persistent; } -FontGlobalContext::FontGlobalContext() : harfbuzz_font_funcs_(nullptr) {} +FontGlobalContext::FontGlobalContext() + : harfbuzz_font_funcs_(nullptr), + default_locale_(nullptr), + system_locale_(nullptr), + default_locale_for_han_(nullptr), + has_default_locale_for_han_(false) {} void FontGlobalContext::ClearMemory() { if (!Get(kDoNotCreate)) @@ -28,4 +33,14 @@ GetFontCache().Invalidate(); } +void FontGlobalContext::ClearForTesting() { + FontGlobalContext* ctx = Get(); + ctx->default_locale_ = nullptr; + ctx->system_locale_ = nullptr; + ctx->default_locale_for_han_ = nullptr; + ctx->has_default_locale_for_han_ = false; + ctx->layout_locale_map_.clear(); + ctx->font_cache_.Invalidate(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h b/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h index 7e9c944..4571cd3 100644 --- a/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h +++ b/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h
@@ -17,8 +17,12 @@ namespace blink { +class LayoutLocale; class FontCache; +using LayoutLocaleMap = + HashMap<AtomicString, RefPtr<LayoutLocale>, CaseFoldingHash>; + enum CreateIfNeeded { kDoNotCreate, kCreate }; // FontGlobalContext contains non-thread-safe, thread-specific data used for @@ -43,9 +47,47 @@ Get()->harfbuzz_font_funcs_ = funcs; } + static inline LayoutLocaleMap& GetLayoutLocaleMap() { + return Get()->layout_locale_map_; + } + + static inline const LayoutLocale* GetDefaultLayoutLocale() { + return Get()->default_locale_; + } + static inline void SetDefaultLayoutLocale(const LayoutLocale* locale) { + Get()->default_locale_ = locale; + } + static inline const LayoutLocale* GetSystemLayoutLocale() { + return Get()->system_locale_; + } + static inline void SetSystemLayoutLocale(const LayoutLocale* locale) { + Get()->system_locale_ = locale; + } + + static inline const LayoutLocale* GetDefaultLocaleForHan() { + FontGlobalContext* ctx = Get(); + DCHECK(ctx->has_default_locale_for_han_); + return ctx->default_locale_for_han_; + } + static inline void SetDefaultLocaleForHan(const LayoutLocale* locale) { + FontGlobalContext* ctx = Get(); + ctx->default_locale_for_han_ = locale; + ctx->has_default_locale_for_han_ = true; + } + static inline void InvalidateLocaleForHan() { + FontGlobalContext* ctx = Get(); + ctx->default_locale_for_han_ = nullptr; + ctx->has_default_locale_for_han_ = false; + } + static inline bool HasDefaultLocaleForHan() { + return Get()->has_default_locale_for_han_; + } + // Called by MemoryCoordinator to clear memory. static void ClearMemory(); + static void ClearForTesting(); + private: friend class WTF::ThreadSpecific<FontGlobalContext>; @@ -57,6 +99,12 @@ HarfBuzzFontCache harf_buzz_font_cache_; hb_font_funcs_t* harfbuzz_font_funcs_; + + LayoutLocaleMap layout_locale_map_; + const LayoutLocale* default_locale_; + const LayoutLocale* system_locale_; + const LayoutLocale* default_locale_for_han_; + bool has_default_locale_for_han_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp index 77e4baf..a792987 100644 --- a/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp
@@ -23,7 +23,7 @@ : limit(the_limit), render_orientation(the_render_orientation) {} }; -class OrientationIteratorTest : public testing::Test { +class OrientationIteratorTest : public ::testing::Test { protected: void CheckRuns(const Vector<TestRun>& runs) { String text(g_empty_string16_bit);
diff --git a/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp index 52631ff..6bb487e 100644 --- a/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp
@@ -284,7 +284,7 @@ kGreek3 + kHan2 + kLatin, }; -class ScriptRunIteratorTest : public testing::Test { +class ScriptRunIteratorTest : public ::testing::Test { protected: void CheckRuns(const Vector<TestRun>& runs) { String text(g_empty_string16_bit); @@ -614,7 +614,7 @@ CHECK_RUNS({{"100-ാം", USCRIPT_MALAYALAM}}); } -class ScriptRunIteratorICUDataTest : public testing::Test { +class ScriptRunIteratorICUDataTest : public ::testing::Test { public: ScriptRunIteratorICUDataTest() : max_extensions_(0), max_extensions_codepoint_(0xffff) {
diff --git a/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp index 221c77c..8728265 100644 --- a/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp
@@ -23,7 +23,7 @@ : limit(the_limit), small_caps_behavior(the_small_caps_behavior) {} }; -class SmallCapsIteratorTest : public testing::Test { +class SmallCapsIteratorTest : public ::testing::Test { protected: void CheckRuns(const Vector<TestRun>& runs) { String text(g_empty_string16_bit);
diff --git a/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp index 04ff8c8..0e0e377 100644 --- a/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp
@@ -23,7 +23,7 @@ : limit(the_limit), font_fallback_priority(the_font_fallback_priority) {} }; -class SymbolsIteratorTest : public testing::Test { +class SymbolsIteratorTest : public ::testing::Test { protected: void CheckRuns(const Vector<TestRun>& runs) { String text(g_empty_string16_bit);
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp index 9b00d6c..11a6a12 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp
@@ -40,7 +40,7 @@ font_fallback_priority(the_font_fallback_priority) {} }; -class RunSegmenterTest : public testing::Test { +class RunSegmenterTest : public ::testing::Test { protected: void CheckRuns(const Vector<SegmenterTestRun>& runs, FontOrientation orientation) {
diff --git a/third_party/WebKit/Source/platform/geometry/FloatBoxTestHelpers.cpp b/third_party/WebKit/Source/platform/geometry/FloatBoxTestHelpers.cpp index 136fbe0..3b1ed38 100644 --- a/third_party/WebKit/Source/platform/geometry/FloatBoxTestHelpers.cpp +++ b/third_party/WebKit/Source/platform/geometry/FloatBoxTestHelpers.cpp
@@ -54,7 +54,7 @@ if (!ApproximatelyEqual(m, n)) { return ::testing::AssertionFailure() << " Value of:" << n_expr << std::endl - << " Actual:" << testing::PrintToString(n) << std::endl + << " Actual:" << ::testing::PrintToString(n) << std::endl << "Expected Approx:" << expr << std::endl << " Which is:" << ::testing::PrintToString(m); } @@ -70,7 +70,7 @@ if (!ApproximatelyEqual(m, new_m)) { return ::testing::AssertionFailure() << " Value of:" << n_expr << std::endl - << " Actual:" << testing::PrintToString(n) << std::endl + << " Actual:" << ::testing::PrintToString(n) << std::endl << "Not Contained in:" << expr << std::endl << " Which is:" << ::testing::PrintToString(m); }
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp index 2ce9e62..161a5e2 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -53,12 +53,12 @@ #include <memory> -using testing::AnyNumber; -using testing::AtLeast; -using testing::InSequence; -using testing::Return; -using testing::Test; -using testing::_; +using ::testing::AnyNumber; +using ::testing::AtLeast; +using ::testing::InSequence; +using ::testing::Return; +using ::testing::Test; +using ::testing::_; namespace blink {
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainerTest.cpp b/third_party/WebKit/Source/platform/graphics/ContiguousContainerTest.cpp index d51c1da..c5ddbd3 100644 --- a/third_party/WebKit/Source/platform/graphics/ContiguousContainerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainerTest.cpp
@@ -80,9 +80,9 @@ auto& destructible = list.AllocateAndConstruct<MockDestructible>(); EXPECT_EQ(&destructible, &list.First()); - testing::MockFunction<void()> separator; + ::testing::MockFunction<void()> separator; { - testing::InSequence s; + ::testing::InSequence s; EXPECT_CALL(destructible, Destruct()); EXPECT_CALL(separator, Call()); EXPECT_CALL(destructible, Destruct()).Times(0); @@ -97,9 +97,9 @@ auto& destructible = list.AllocateAndConstruct<MockDestructible>(); EXPECT_EQ(&destructible, &list.First()); - testing::MockFunction<void()> separator; + ::testing::MockFunction<void()> separator; { - testing::InSequence s; + ::testing::InSequence s; EXPECT_CALL(destructible, Destruct()); EXPECT_CALL(separator, Call()); EXPECT_CALL(destructible, Destruct()).Times(0); @@ -114,13 +114,13 @@ // free to use more space if the allocator provides it. ContiguousContainer<MockDestructible> list(sizeof(MockDestructible), 1 * sizeof(MockDestructible)); - testing::MockFunction<void()> separator; + ::testing::MockFunction<void()> separator; // We should be okay to allocate and remove a single one, like before. list.AllocateAndConstruct<MockDestructible>(); EXPECT_EQ(1u, list.size()); { - testing::InSequence s; + ::testing::InSequence s; EXPECT_CALL(list[0], Destruct()); EXPECT_CALL(separator, Call()); EXPECT_CALL(list[0], Destruct()).Times(0); @@ -129,7 +129,7 @@ separator.Call(); EXPECT_EQ(0u, list.size()); - testing::Mock::VerifyAndClearExpectations(&separator); + ::testing::Mock::VerifyAndClearExpectations(&separator); // We should also be okay to allocate and remove multiple. list.AllocateAndConstruct<MockDestructible>(); @@ -141,7 +141,7 @@ EXPECT_EQ(6u, list.size()); { // The last three should be destroyed by removeLast. - testing::InSequence s; + ::testing::InSequence s; EXPECT_CALL(list[5], Destruct()); EXPECT_CALL(separator, Call()); EXPECT_CALL(list[5], Destruct()).Times(0);
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp index 3595d7f3..bb44542 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
@@ -53,7 +53,7 @@ namespace blink { -class GraphicsLayerTest : public testing::Test { +class GraphicsLayerTest : public ::testing::Test { public: GraphicsLayerTest() { clip_layer_ = WTF::WrapUnique(new FakeGraphicsLayer(&client_));
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp index 3b4b653..af9580e 100644 --- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -21,7 +21,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::Test; +using ::testing::Test; namespace blink {
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp similarity index 79% rename from third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp rename to third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp index a19b255..f5c7cc1 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.cpp
@@ -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 "platform/graphics/CanvasSurfaceLayerBridge.h" +#include "platform/graphics/SurfaceLayerBridge.h" #include "cc/layers/layer.h" #include "cc/layers/solid_color_layer.h" @@ -25,16 +25,14 @@ namespace blink { namespace { - -class OffscreenCanvasSurfaceReferenceFactory +class SequenceSurfaceReferenceFactoryImpl : public cc::SequenceSurfaceReferenceFactory { public: - OffscreenCanvasSurfaceReferenceFactory( - base::WeakPtr<CanvasSurfaceLayerBridge> bridge) + SequenceSurfaceReferenceFactoryImpl(base::WeakPtr<SurfaceLayerBridge> bridge) : bridge_(bridge) {} private: - ~OffscreenCanvasSurfaceReferenceFactory() override = default; + ~SequenceSurfaceReferenceFactoryImpl() override = default; // cc::SequenceSurfaceReferenceFactory implementation: void RequireSequence(const cc::SurfaceId& id, @@ -48,16 +46,15 @@ bridge_->SatisfyCallback(sequence); } - base::WeakPtr<CanvasSurfaceLayerBridge> bridge_; + base::WeakPtr<SurfaceLayerBridge> bridge_; - DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasSurfaceReferenceFactory); + DISALLOW_COPY_AND_ASSIGN(SequenceSurfaceReferenceFactoryImpl); }; } // namespace -CanvasSurfaceLayerBridge::CanvasSurfaceLayerBridge( - CanvasSurfaceLayerBridgeObserver* observer, - WebLayerTreeView* layer_tree_view) +SurfaceLayerBridge::SurfaceLayerBridge(SurfaceLayerBridgeObserver* observer, + WebLayerTreeView* layer_tree_view) : weak_factory_(this), observer_(observer), binding_(this), @@ -65,7 +62,7 @@ parent_frame_sink_id_(layer_tree_view ? layer_tree_view->GetFrameSinkId() : cc::FrameSinkId()) { ref_factory_ = - new OffscreenCanvasSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); + new SequenceSurfaceReferenceFactoryImpl(weak_factory_.GetWeakPtr()); DCHECK(!service_.is_bound()); mojom::blink::OffscreenCanvasProviderPtr provider; @@ -81,23 +78,32 @@ mojo::MakeRequest(&service_)); } -CanvasSurfaceLayerBridge::~CanvasSurfaceLayerBridge() { +SurfaceLayerBridge::~SurfaceLayerBridge() { observer_ = nullptr; if (web_layer_) { GraphicsLayer::UnregisterContentsLayer(web_layer_.get()); } } -void CanvasSurfaceLayerBridge::CreateSolidColorLayer() { +void SurfaceLayerBridge::SatisfyCallback(const cc::SurfaceSequence& sequence) { + service_->Satisfy(sequence); +} + +void SurfaceLayerBridge::RequireCallback(const cc::SurfaceId& surface_id, + const cc::SurfaceSequence& sequence) { + service_->Require(surface_id, sequence); +} + +void SurfaceLayerBridge::CreateSolidColorLayer() { cc_layer_ = cc::SolidColorLayer::Create(); cc_layer_->SetBackgroundColor(SK_ColorTRANSPARENT); + web_layer_ = Platform::Current()->CompositorSupport()->CreateLayerFromCCLayer( cc_layer_.get()); GraphicsLayer::RegisterContentsLayer(web_layer_.get()); } -void CanvasSurfaceLayerBridge::OnSurfaceCreated( - const cc::SurfaceInfo& surface_info) { +void SurfaceLayerBridge::OnSurfaceCreated(const cc::SurfaceInfo& surface_info) { if (!current_surface_id_.is_valid() && surface_info.is_valid()) { // First time a SurfaceId is received current_surface_id_ = surface_info.id(); @@ -125,19 +131,9 @@ surface_layer->SetFallbackSurfaceInfo(surface_info); } - observer_->OnWebLayerReplaced(); + if (observer_) + observer_->OnWebLayerReplaced(); cc_layer_->SetBounds(surface_info.size_in_pixels()); } -void CanvasSurfaceLayerBridge::SatisfyCallback( - const cc::SurfaceSequence& sequence) { - service_->Satisfy(sequence); -} - -void CanvasSurfaceLayerBridge::RequireCallback( - const cc::SurfaceId& surface_id, - const cc::SurfaceSequence& sequence) { - service_->Require(surface_id, sequence); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h b/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.h similarity index 66% rename from third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h rename to third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.h index c82436c..1eb2e3a 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h +++ b/third_party/WebKit/Source/platform/graphics/SurfaceLayerBridge.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 CanvasSurfaceLayerBridge_h -#define CanvasSurfaceLayerBridge_h +#ifndef SurfaceLayerBridge_h +#define SurfaceLayerBridge_h #include <memory> #include "base/memory/ref_counted.h" @@ -12,6 +12,7 @@ #include "cc/surfaces/surface_reference_factory.h" #include "mojo/public/cpp/bindings/binding.h" #include "platform/PlatformExport.h" +#include "public/platform/WebSurfaceLayerBridge.h" #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom-blink.h" namespace cc { @@ -24,41 +25,45 @@ class WebLayer; class WebLayerTreeView; -class PLATFORM_EXPORT CanvasSurfaceLayerBridgeObserver { +class PLATFORM_EXPORT SurfaceLayerBridgeObserver { public: - CanvasSurfaceLayerBridgeObserver() {} - virtual ~CanvasSurfaceLayerBridgeObserver() {} + SurfaceLayerBridgeObserver() {} + virtual ~SurfaceLayerBridgeObserver() {} virtual void OnWebLayerReplaced() = 0; }; -class PLATFORM_EXPORT CanvasSurfaceLayerBridge - : NON_EXPORTED_BASE( - public blink::mojom::blink::OffscreenCanvasSurfaceClient) { +class PLATFORM_EXPORT SurfaceLayerBridge + : public NON_EXPORTED_BASE( + blink::mojom::blink::OffscreenCanvasSurfaceClient), + public WebSurfaceLayerBridge { public: - explicit CanvasSurfaceLayerBridge(CanvasSurfaceLayerBridgeObserver*, - WebLayerTreeView*); - ~CanvasSurfaceLayerBridge(); + SurfaceLayerBridge(SurfaceLayerBridgeObserver*, WebLayerTreeView*); + virtual ~SurfaceLayerBridge(); + void CreateSolidColorLayer(); - WebLayer* GetWebLayer() const { return web_layer_.get(); } - const cc::FrameSinkId& GetFrameSinkId() const { return frame_sink_id_; } // Implementation of blink::mojom::blink::OffscreenCanvasSurfaceClient void OnSurfaceCreated(const cc::SurfaceInfo&) override; - void SatisfyCallback(const cc::SurfaceSequence&); void RequireCallback(const cc::SurfaceId&, const cc::SurfaceSequence&); + // Implementation of WebSurfaceLayerBridge. + WebLayer* GetWebLayer() const override { return web_layer_.get(); } + + const cc::FrameSinkId& GetFrameSinkId() const { return frame_sink_id_; } + private: + mojom::blink::OffscreenCanvasSurfacePtr service_; + scoped_refptr<cc::Layer> cc_layer_; std::unique_ptr<WebLayer> web_layer_; scoped_refptr<cc::SurfaceReferenceFactory> ref_factory_; - base::WeakPtrFactory<CanvasSurfaceLayerBridge> weak_factory_; + base::WeakPtrFactory<SurfaceLayerBridge> weak_factory_; - CanvasSurfaceLayerBridgeObserver* observer_; + SurfaceLayerBridgeObserver* observer_; - mojom::blink::OffscreenCanvasSurfacePtr service_; mojo::Binding<blink::mojom::blink::OffscreenCanvasSurfaceClient> binding_; const cc::FrameSinkId frame_sink_id_; @@ -68,4 +73,4 @@ } // namespace blink -#endif // CanvasSurfaceLayerBridge_h +#endif // SurfaceLayerBridge_h
diff --git a/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp b/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp index 34c6414..ab4cb85 100644 --- a/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp
@@ -31,7 +31,7 @@ #include "platform/graphics/filters/SourceGraphic.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::Test; +using ::testing::Test; namespace blink {
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index b5867526..db0a033 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -47,8 +47,8 @@ #include "public/platform/Platform.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::Test; -using testing::_; +using ::testing::Test; +using ::testing::_; namespace blink { @@ -410,7 +410,7 @@ kDisableMultisampling); CHECK(drawing_buffer_); SetAndSaveRestoreState(true); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); } void TearDown() override { @@ -438,7 +438,7 @@ &release_callback)); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); GLuint image_id2 = gl_->NextImageIdToBeCreated(); @@ -452,7 +452,7 @@ VerifyStateWasRestored(); release_callback->Run(gpu::SyncToken(), false /* lostResource */); VerifyStateWasRestored(); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); GLuint image_id3 = gl_->NextImageIdToBeCreated(); EXPECT_CALL(*gl_, BindTexImage2DMock(image_id3)).Times(1); @@ -462,7 +462,7 @@ &release_callback)); EXPECT_EQ(alternate_size, gl_->MostRecentlyProducedSize()); EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); GLuint image_id4 = gl_->NextImageIdToBeCreated(); EXPECT_CALL(*gl_, BindTexImage2DMock(image_id4)).Times(1); @@ -475,7 +475,7 @@ VerifyStateWasRestored(); release_callback->Run(gpu::SyncToken(), false /* lostResource */); VerifyStateWasRestored(); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); GLuint image_id5 = gl_->NextImageIdToBeCreated(); EXPECT_CALL(*gl_, BindTexImage2DMock(image_id5)).Times(1); @@ -485,7 +485,7 @@ &release_callback)); EXPECT_EQ(initial_size, gl_->MostRecentlyProducedSize()); EXPECT_TRUE(texture_mailbox.is_overlay_candidate()); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); // Prepare one final mailbox and verify that it's the correct size. release_callback->Run(gpu::SyncToken(), false /* lostResource */); @@ -501,7 +501,7 @@ EXPECT_CALL(*gl_, DestroyImageMock(image_id4)).Times(1); EXPECT_CALL(*gl_, ReleaseTexImage2DMock(image_id4)).Times(1); drawing_buffer_->BeginDestruction(); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); } TEST_F(DrawingBufferImageChromiumTest, allocationFailure) { @@ -521,7 +521,7 @@ EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox1, &release_callback1)); EXPECT_TRUE(texture_mailbox1.is_overlay_candidate()); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); // Force image CHROMIUM creation failure. Request another mailbox. It should @@ -541,7 +541,7 @@ EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox3, &release_callback3)); EXPECT_TRUE(texture_mailbox3.is_overlay_candidate()); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); release_callback1->Run(gpu::SyncToken(), false /* lostResource */); @@ -551,7 +551,7 @@ EXPECT_CALL(*gl_, DestroyImageMock(_)).Times(3); EXPECT_CALL(*gl_, ReleaseTexImage2DMock(_)).Times(3); drawing_buffer_->BeginDestruction(); - testing::Mock::VerifyAndClearExpectations(gl_); + ::testing::Mock::VerifyAndClearExpectations(gl_); } class DepthStencilTrackingGLES2Interface
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp index e26157a..39b1ff6 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp
@@ -10,7 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/khronos/GLES2/gl2ext.h" -using testing::Test; +using ::testing::Test; namespace blink {
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversionTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversionTest.cpp index 128ae15..4a8fb4a0 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversionTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversionTest.cpp
@@ -9,7 +9,7 @@ namespace blink { -class WebGLImageConversionTest : public testing::Test { +class WebGLImageConversionTest : public ::testing::Test { protected: void UnpackPixels(const uint16_t* source_data, WebGLImageConversion::DataFormat source_data_format,
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CullRectTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/CullRectTest.cpp index f2950ba0..a7c508e 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/CullRectTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/CullRectTest.cpp
@@ -10,7 +10,7 @@ namespace blink { -class CullRectTest : public testing::Test { +class CullRectTest : public ::testing::Test { protected: IntRect Rect(const CullRect& cull_rect) { return cull_rect.rect_; } };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItemTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItemTest.cpp index b4c9577..c9a9f1a 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItemTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItemTest.cpp
@@ -15,7 +15,7 @@ namespace blink { namespace { -using testing::_; +using ::testing::_; class DrawingDisplayItemTest : public ::testing::Test { protected:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp index 4f9939ac..c251780d 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -23,7 +23,7 @@ using blink::testing::CreateOpacityOnlyEffect; using blink::testing::DefaultPaintChunkProperties; -using testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAre; namespace blink {
diff --git a/third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp b/third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp index 7ef6296..fade747 100644 --- a/third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp +++ b/third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp
@@ -175,7 +175,7 @@ INSTANTIATE_TEST_CASE_P(LinkHeaderTest, SingleLinkHeaderTest, - testing::ValuesIn(g_single_test_cases)); + ::testing::ValuesIn(g_single_test_cases)); struct DoubleTestCase { const char* header_value; @@ -219,7 +219,7 @@ INSTANTIATE_TEST_CASE_P(LinkHeaderTest, DoubleLinkHeaderTest, - testing::ValuesIn(g_double_test_cases)); + ::testing::ValuesIn(g_double_test_cases)); struct CrossOriginTestCase { const char* header_value; @@ -281,7 +281,7 @@ INSTANTIATE_TEST_CASE_P(LinkHeaderTest, CrossOriginLinkHeaderTest, - testing::ValuesIn(g_cross_origin_test_cases)); + ::testing::ValuesIn(g_cross_origin_test_cases)); } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/base/intrusive_heap_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/intrusive_heap_unittest.cc index eb28fbb9..1240940 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/intrusive_heap_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/intrusive_heap_unittest.cc
@@ -278,7 +278,8 @@ heap.Pop(); } - EXPECT_THAT(results, testing::ElementsAre(0, 2, 4, 6, 8, 12, 14, 16, 17, 18)); + EXPECT_THAT(results, + ::testing::ElementsAre(0, 2, 4, 6, 8, 12, 14, 16, 17, 18)); } TEST_F(IntrusiveHeapTest, ChangeKeyUpButDoesntMove) { @@ -297,7 +298,8 @@ heap.Pop(); } - EXPECT_THAT(results, testing::ElementsAre(0, 2, 4, 6, 8, 11, 12, 14, 16, 18)); + EXPECT_THAT(results, + ::testing::ElementsAre(0, 2, 4, 6, 8, 11, 12, 14, 16, 18)); } TEST_F(IntrusiveHeapTest, ChangeKeyDown) { @@ -316,7 +318,8 @@ heap.Pop(); } - EXPECT_THAT(results, testing::ElementsAre(0, 1, 2, 4, 6, 8, 12, 14, 16, 18)); + EXPECT_THAT(results, + ::testing::ElementsAre(0, 1, 2, 4, 6, 8, 12, 14, 16, 18)); } TEST_F(IntrusiveHeapTest, ChangeKeyDownButDoesntMove) { @@ -335,7 +338,8 @@ heap.Pop(); } - EXPECT_THAT(results, testing::ElementsAre(0, 2, 4, 6, 8, 9, 12, 14, 16, 18)); + EXPECT_THAT(results, + ::testing::ElementsAre(0, 2, 4, 6, 8, 9, 12, 14, 16, 18)); } TEST_F(IntrusiveHeapTest, ChangeKeyCheckAllFinalPositions) {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/queueing_time_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/queueing_time_estimator_unittest.cc index 1a5fa904..8bff10a 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/queueing_time_estimator_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/queueing_time_estimator_unittest.cc
@@ -11,7 +11,7 @@ namespace blink { namespace scheduler { -using QueueingTimeEstimatorTest = testing::Test; +using QueueingTimeEstimatorTest = ::testing::Test; class TestQueueingTimeEstimatorClient : public QueueingTimeEstimator::Client { public: @@ -58,7 +58,7 @@ estimator.OnTopLevelTaskCompleted(time); EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAre(base::TimeDelta::FromMilliseconds(300))); + ::testing::ElementsAre(base::TimeDelta::FromMilliseconds(300))); } // One 20 second long task, starting 3 seconds into the first window. @@ -90,11 +90,11 @@ estimator.OnTopLevelTaskCompleted(time); EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAre(base::TimeDelta::FromMilliseconds(7600), - base::TimeDelta::FromMilliseconds(15500), - base::TimeDelta::FromMilliseconds(10500), - base::TimeDelta::FromMilliseconds(5500), - base::TimeDelta::FromMilliseconds(900))); + ::testing::ElementsAre(base::TimeDelta::FromMilliseconds(7600), + base::TimeDelta::FromMilliseconds(15500), + base::TimeDelta::FromMilliseconds(10500), + base::TimeDelta::FromMilliseconds(5500), + base::TimeDelta::FromMilliseconds(900))); } // The main thread is considered unresponsive during a single long task. In this @@ -253,11 +253,11 @@ estimator.OnTopLevelTaskCompleted(time); EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAre(base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(100))); + ::testing::ElementsAre(base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(100))); } // If a task is too long, we assume it's invalid. Perhaps the user's machine @@ -290,14 +290,14 @@ estimator.OnTopLevelTaskCompleted(time); EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAre(base::TimeDelta::FromMilliseconds(100), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(0), - base::TimeDelta::FromMilliseconds(100))); + ::testing::ElementsAre(base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(100))); } // ^ Instantaneous queuing time @@ -330,16 +330,16 @@ estimator.OnTopLevelTaskCompleted(time); EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAre(base::TimeDelta::FromMilliseconds(900), - base::TimeDelta::FromMilliseconds(1600), - base::TimeDelta::FromMilliseconds(2100), - base::TimeDelta::FromMilliseconds(2400), - base::TimeDelta::FromMilliseconds(2500), - base::TimeDelta::FromMilliseconds(1600), - base::TimeDelta::FromMilliseconds(900), - base::TimeDelta::FromMilliseconds(400), - base::TimeDelta::FromMilliseconds(100), - base::TimeDelta::FromMilliseconds(0))); + ::testing::ElementsAre(base::TimeDelta::FromMilliseconds(900), + base::TimeDelta::FromMilliseconds(1600), + base::TimeDelta::FromMilliseconds(2100), + base::TimeDelta::FromMilliseconds(2400), + base::TimeDelta::FromMilliseconds(2500), + base::TimeDelta::FromMilliseconds(1600), + base::TimeDelta::FromMilliseconds(900), + base::TimeDelta::FromMilliseconds(400), + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(0))); } // ^ Instantaneous queuing time @@ -388,7 +388,7 @@ base::TimeDelta::FromMilliseconds(100), base::TimeDelta::FromMilliseconds(0)}; EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAreArray(expected_durations)); + ::testing::ElementsAreArray(expected_durations)); } // ^ Instantaneous queuing time @@ -445,7 +445,7 @@ base::TimeDelta::FromMilliseconds(0)}; EXPECT_THAT(client.expected_queueing_times(), - testing::ElementsAreArray(expected_durations)); + ::testing::ElementsAreArray(expected_durations)); } } // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc index b2776a15..4c33e1d2 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
@@ -60,7 +60,7 @@ DISALLOW_COPY_AND_ASSIGN(PerfTestTimeDomain); }; -class TaskQueueManagerPerfTest : public testing::Test { +class TaskQueueManagerPerfTest : public ::testing::Test { public: TaskQueueManagerPerfTest() : num_queues_(0),
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc index d21cd7b0..5ab22a8 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -33,13 +33,13 @@ #include "platform/scheduler/base/work_queue_sets.h" #include "testing/gmock/include/gmock/gmock.h" -using testing::AnyNumber; -using testing::Contains; -using testing::ElementsAre; -using testing::ElementsAreArray; -using testing::Mock; -using testing::Not; -using testing::_; +using ::testing::AnyNumber; +using ::testing::Contains; +using ::testing::ElementsAre; +using ::testing::ElementsAreArray; +using ::testing::Mock; +using ::testing::Not; +using ::testing::_; using blink::scheduler::internal::EnqueueOrder; namespace blink { @@ -83,7 +83,7 @@ ~MessageLoopTaskRunner() override {} }; -class TaskQueueManagerTest : public testing::Test { +class TaskQueueManagerTest : public ::testing::Test { public: TaskQueueManagerTest() {} void DeleteTaskQueueManager() { manager_.reset(); } @@ -1781,7 +1781,7 @@ .Times(1); runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay1s); runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay10s); - testing::Mock::VerifyAndClearExpectations(&observer); + ::testing::Mock::VerifyAndClearExpectations(&observer); std::unique_ptr<TaskQueue::QueueEnabledVoter> voter0 = runners_[0]->CreateQueueEnabledVoter();
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc index c98d2816..96f1c6c 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
@@ -19,7 +19,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; +using ::testing::_; namespace blink { namespace scheduler { @@ -44,7 +44,7 @@ using TaskQueueSelector::enabled_selector_for_test; }; -class TaskQueueSelectorTest : public testing::Test { +class TaskQueueSelectorTest : public ::testing::Test { public: TaskQueueSelectorTest() : test_closure_(base::Bind(&TaskQueueSelectorTest::TestFunction)) {} @@ -163,21 +163,21 @@ TEST_F(TaskQueueSelectorTest, TestDefaultPriority) { size_t queue_order[] = {4, 3, 2, 1, 0}; PushTasks(queue_order, 5); - EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4, 3, 2, 1, 0)); } TEST_F(TaskQueueSelectorTest, TestHighPriority) { size_t queue_order[] = {0, 1, 2, 3, 4}; PushTasks(queue_order, 5); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::HIGH_PRIORITY); - EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 0, 1, 3, 4)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 0, 1, 3, 4)); } TEST_F(TaskQueueSelectorTest, TestLowPriority) { size_t queue_order[] = {0, 1, 2, 3, 4}; PushTasks(queue_order, 5); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::LOW_PRIORITY); - EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3, 4, 2)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(0, 1, 3, 4, 2)); } TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) { @@ -187,7 +187,7 @@ TaskQueue::BEST_EFFORT_PRIORITY); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::LOW_PRIORITY); selector_.SetQueuePriority(task_queues_[3].get(), TaskQueue::HIGH_PRIORITY); - EXPECT_THAT(PopTasks(), testing::ElementsAre(3, 1, 4, 2, 0)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(3, 1, 4, 2, 0)); } TEST_F(TaskQueueSelectorTest, TestControlPriority) { @@ -198,7 +198,7 @@ EXPECT_EQ(TaskQueue::CONTROL_PRIORITY, task_queues_[4]->GetQueuePriority()); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::HIGH_PRIORITY); EXPECT_EQ(TaskQueue::HIGH_PRIORITY, task_queues_[2]->GetQueuePriority()); - EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 2, 0, 1, 3)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4, 2, 0, 1, 3)); } TEST_F(TaskQueueSelectorTest, TestObserverWithEnabledQueue) { @@ -235,15 +235,15 @@ // Disabling a queue should not affect its priority. EXPECT_EQ(TaskQueue::NORMAL_PRIORITY, task_queues_[2]->GetQueuePriority()); EXPECT_EQ(TaskQueue::NORMAL_PRIORITY, task_queues_[4]->GetQueuePriority()); - EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(0, 1, 3)); EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(2); EnableQueue(voter2.get()); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::BEST_EFFORT_PRIORITY); - EXPECT_THAT(PopTasks(), testing::ElementsAre(2)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2)); EnableQueue(voter4.get()); - EXPECT_THAT(PopTasks(), testing::ElementsAre(4)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4)); } TEST_F(TaskQueueSelectorTest, TestDisableChangePriorityThenEnable) { @@ -263,7 +263,7 @@ EnableQueue(voter2.get()); EXPECT_EQ(TaskQueue::HIGH_PRIORITY, task_queues_[2]->GetQueuePriority()); - EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 0, 1, 3, 4)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 0, 1, 3, 4)); } TEST_F(TaskQueueSelectorTest, TestEmptyQueues) { @@ -288,7 +288,7 @@ size_t enqueue_order[] = {10, 1, 2, 9, 4}; size_t queue_order[] = {0, 1, 2, 3, 4}; PushTasksWithEnqueueOrder(queue_order, enqueue_order, 5); - EXPECT_THAT(PopTasks(), testing::ElementsAre(1, 2, 4, 3, 0)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(1, 2, 4, 3, 0)); } TEST_F(TaskQueueSelectorTest, TestControlStarvesOthers) { @@ -513,7 +513,7 @@ WorkQueue* chosen_work_queue; EXPECT_CALL(mock_observer, OnTriedToSelectBlockedWorkQueue(_)).Times(1); EXPECT_FALSE(selector.SelectWorkQueueToService(&chosen_work_queue)); - testing::Mock::VerifyAndClearExpectations(&mock_observer); + ::testing::Mock::VerifyAndClearExpectations(&mock_observer); EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(2); @@ -551,7 +551,8 @@ class ChooseOldestWithPriorityTest : public TaskQueueSelectorTest, - public testing::WithParamInterface<ChooseOldestWithPriorityTestParam> {}; + public ::testing::WithParamInterface<ChooseOldestWithPriorityTestParam> { +}; TEST_P(ChooseOldestWithPriorityTest, RoundRobinTest) { task_queues_[0]->immediate_work_queue()->Push( @@ -579,9 +580,10 @@ GetParam().expected_did_starve_immediate_queue); } -INSTANTIATE_TEST_CASE_P(ChooseOldestWithPriorityTest, - ChooseOldestWithPriorityTest, - testing::ValuesIn(kChooseOldestWithPriorityTestCases)); +INSTANTIATE_TEST_CASE_P( + ChooseOldestWithPriorityTest, + ChooseOldestWithPriorityTest, + ::testing::ValuesIn(kChooseOldestWithPriorityTestCases)); } // namespace internal } // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker_unittest.cc index aa3a0955..7e8eb0e 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker_unittest.cc
@@ -4,7 +4,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::ElementsAre; +using ::testing::ElementsAre; namespace blink { namespace scheduler {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc index 0107d4d..d77dee24 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
@@ -15,9 +15,9 @@ #include "platform/scheduler/base/work_queue.h" #include "testing/gmock/include/gmock/gmock.h" -using testing::_; -using testing::AnyNumber; -using testing::Mock; +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Mock; namespace blink { namespace scheduler { @@ -64,7 +64,7 @@ DISALLOW_COPY_AND_ASSIGN(MockTimeDomain); }; -class TimeDomainTest : public testing::Test { +class TimeDomainTest : public ::testing::Test { public: void SetUp() final { time_domain_ = base::WrapUnique(CreateMockTimeDomain()); @@ -194,7 +194,7 @@ EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); EXPECT_EQ(task_queue_.get(), next_task_queue); - testing::Mock::VerifyAndClearExpectations(time_domain_.get()); + ::testing::Mock::VerifyAndClearExpectations(time_domain_.get()); EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(wake_up1)).Times(1); EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, wake_up2)).Times(1); @@ -204,7 +204,7 @@ EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); EXPECT_EQ(task_queue2_.get(), next_task_queue); - testing::Mock::VerifyAndClearExpectations(time_domain_.get()); + ::testing::Mock::VerifyAndClearExpectations(time_domain_.get()); EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(wake_up2)).Times(1);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc index de0b9c4..1beb05c 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc
@@ -16,7 +16,7 @@ namespace internal { -class WorkQueueSetsTest : public testing::Test { +class WorkQueueSetsTest : public ::testing::Test { public: void SetUp() override { work_queue_sets_.reset(new WorkQueueSets(kNumSets, "test"));
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc index 59f5581c..4941dbe 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc
@@ -20,7 +20,7 @@ void NopTask() {} } -class WorkQueueTest : public testing::Test { +class WorkQueueTest : public ::testing::Test { public: void SetUp() override { time_domain_.reset(new RealTimeDomain());
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc index 3473eb7..d106333 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -27,7 +27,7 @@ base::WeakPtrFactory<TestClass> weak_factory_; }; -class IdleCanceledDelayedTaskSweeperTest : public testing::Test, +class IdleCanceledDelayedTaskSweeperTest : public ::testing::Test, public IdleHelper::Delegate { public: IdleCanceledDelayedTaskSweeperTest()
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc index c42e6bb..8901a29 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
@@ -24,12 +24,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; -using testing::AnyNumber; -using testing::AtLeast; -using testing::Exactly; -using testing::Invoke; -using testing::Return; +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::AtLeast; +using ::testing::Exactly; +using ::testing::Invoke; +using ::testing::Return; namespace blink { namespace scheduler { @@ -177,7 +177,7 @@ MOCK_METHOD1(OnPendingTasksChanged, void(bool has_tasks)); }; -class BaseIdleHelperTest : public testing::Test { +class BaseIdleHelperTest : public ::testing::Test { public: BaseIdleHelperTest( base::MessageLoop* message_loop, @@ -427,7 +427,8 @@ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0); } - void ExpectIdlePeriodStartsAndEnds(const testing::Cardinality& cardinality) { + void ExpectIdlePeriodStartsAndEnds( + const ::testing::Cardinality& cardinality) { EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(cardinality); EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(cardinality); } @@ -524,9 +525,9 @@ clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); RunUntilIdle(); // Note we expect task 3 to run last because it's non-nestable. - EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"), - std::string("4"), std::string("5"), - std::string("3"))); + EXPECT_THAT(order, ::testing::ElementsAre(std::string("1"), std::string("2"), + std::string("4"), std::string("5"), + std::string("3"))); } TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriod) { @@ -619,7 +620,7 @@ EXPECT_EQ(3, run_count); EXPECT_THAT( actual_deadlines, - testing::ElementsAre( + ::testing::ElementsAre( clock_before + maximum_idle_period_duration(), clock_before + idle_task_runtime + maximum_idle_period_duration(), clock_before + (2 * idle_task_runtime) + @@ -701,7 +702,7 @@ EXPECT_EQ(2, run_count); EXPECT_THAT( actual_deadlines, - testing::ElementsAre( + ::testing::ElementsAre( clock_before + maximum_idle_period_duration(), clock_before + idle_task_runtime + maximum_idle_period_duration())); } @@ -772,7 +773,7 @@ EXPECT_EQ(2, run_count); EXPECT_THAT( actual_deadlines, - testing::ElementsAre( + ::testing::ElementsAre( clock_before + maximum_idle_period_duration(), clock_before + idle_task_runtime + maximum_idle_period_duration())); @@ -1126,7 +1127,7 @@ base::TimeTicks deadline_in_task; { - testing::InSequence dummy; + ::testing::InSequence dummy; // This will be called once. I.e when the one and only task is posted. EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(true)).Times(1); // This will be called once. I.e when the one and only task completes. @@ -1157,7 +1158,7 @@ base::TimeTicks deadline_in_task; { - testing::InSequence dummy; + ::testing::InSequence dummy; // This will be called 3 times. I.e when T1 and T2 are posted and when T1 // completes. EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(true)).Times(3);
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc index 5e6ab991..f3dae923 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
@@ -18,10 +18,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; -using testing::AnyNumber; -using testing::Invoke; -using testing::Return; +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Invoke; +using ::testing::Return; namespace blink { namespace scheduler { @@ -47,7 +47,7 @@ }; // namespace -class SchedulerHelperTest : public testing::Test { +class SchedulerHelperTest : public ::testing::Test { public: SchedulerHelperTest() : clock_(new base::SimpleTestTickClock()), @@ -105,8 +105,8 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("D3"), std::string("D4"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("D3"), std::string("D4"))); } TEST_F(SchedulerHelperTest, TestRentrantTask) { @@ -118,7 +118,7 @@ &count, 5)); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4)); + EXPECT_THAT(run_order, ::testing::ElementsAre(0, 1, 2, 3, 4)); } TEST_F(SchedulerHelperTest, IsShutdown) {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc index 5781866..877bc196 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
@@ -13,10 +13,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; -using testing::AnyOf; -using testing::ElementsAre; -using testing::Invoke; +using ::testing::_; +using ::testing::AnyOf; +using ::testing::ElementsAre; +using ::testing::Invoke; namespace blink { namespace scheduler { @@ -70,7 +70,7 @@ } // namespace -class WebThreadImplForWorkerSchedulerTest : public testing::Test { +class WebThreadImplForWorkerSchedulerTest : public ::testing::Test { public: WebThreadImplForWorkerSchedulerTest() {} @@ -173,7 +173,8 @@ // Sometimes we get an internal scheduler task running before or after // TestTask as well. This is not a bug, and we need to make sure the test // doesn't fail when that happens. - EXPECT_THAT(calls, testing::HasSubstr("willProcessTask run didProcessTask")); + EXPECT_THAT(calls, + ::testing::HasSubstr("willProcessTask run didProcessTask")); } TEST_F(WebThreadImplForWorkerSchedulerTest, TestShutdown) {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc index 2fb7153..2725937 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
@@ -14,7 +14,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::ElementsAreArray; +using ::testing::ElementsAreArray; namespace blink { namespace scheduler { @@ -28,7 +28,7 @@ } // namespace -class WorkerGlobalScopeSchedulerTest : public testing::Test { +class WorkerGlobalScopeSchedulerTest : public ::testing::Test { public: WorkerGlobalScopeSchedulerTest() : clock_(new base::SimpleTestTickClock()), @@ -76,7 +76,7 @@ RunUntilIdle(); PostTestTask(&run_order, "T3"); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2", "T3")); + EXPECT_THAT(run_order, ::testing::ElementsAre("T1", "T2", "T3")); // Tasks should not run after the scheduler is disposed of. global_scope_scheduler_->Dispose();
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc index e95e377..67331cf5 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
@@ -16,7 +16,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::ElementsAreArray; +using ::testing::ElementsAreArray; namespace blink { namespace scheduler { @@ -90,7 +90,7 @@ std::vector<std::string>* timeline_; // NOT OWNED }; -class WorkerSchedulerImplTest : public testing::Test { +class WorkerSchedulerImplTest : public ::testing::Test { public: WorkerSchedulerImplTest() : clock_(new base::SimpleTestTickClock()), @@ -190,8 +190,8 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("D3"), std::string("D4"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("D3"), std::string("D4"))); } TEST_F(WorkerSchedulerImplTest, TestPostIdleTask) { @@ -201,7 +201,7 @@ PostTestTasks(&run_order, "I1"); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("I1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("I1"))); } TEST_F(WorkerSchedulerImplTest, TestPostDefaultAndIdleTasks) { @@ -212,8 +212,8 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D2"), std::string("D3"), - std::string("D4"), std::string("I1"))); + ::testing::ElementsAre(std::string("D2"), std::string("D3"), + std::string("D4"), std::string("I1"))); } TEST_F(WorkerSchedulerImplTest, TestPostDefaultDelayedAndIdleTasks) { @@ -228,9 +228,9 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D2"), std::string("D3"), - std::string("D4"), std::string("I1"), - std::string("DELAYED"))); + ::testing::ElementsAre(std::string("D2"), std::string("D3"), + std::string("D4"), std::string("I1"), + std::string("DELAYED"))); } TEST_F(WorkerSchedulerImplTest, TestIdleTaskWhenIsNotQuiescent) { @@ -325,8 +325,8 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D3"), std::string("I1"), - std::string("I2"))); + ::testing::ElementsAre(std::string("D3"), std::string("I1"), + std::string("I2"))); } void PostIdleTask(std::vector<std::string>* timeline,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc index 7351924..b6b847e7 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
@@ -17,7 +17,7 @@ namespace blink { namespace scheduler { -class AutoAdvancingVirtualTimeDomainTest : public testing::Test { +class AutoAdvancingVirtualTimeDomainTest : public ::testing::Test { public: AutoAdvancingVirtualTimeDomainTest() {} ~AutoAdvancingVirtualTimeDomainTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc index b80dc892..5e2c42b 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
@@ -26,7 +26,7 @@ namespace blink { namespace scheduler { -class BudgetPoolTest : public testing::Test { +class BudgetPoolTest : public ::testing::Test { public: BudgetPoolTest() {} ~BudgetPoolTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc index 635eb19..64c47bd 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc
@@ -14,7 +14,7 @@ namespace blink { namespace scheduler { -class DeadlineTaskRunnerTest : public testing::Test { +class DeadlineTaskRunnerTest : public ::testing::Test { public: DeadlineTaskRunnerTest() {} ~DeadlineTaskRunnerTest() override {} @@ -45,7 +45,7 @@ deadline_task_runner_->SetDeadline(FROM_HERE, delay, clock_->NowTicks()); RunUntilIdle(); - EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay)); + EXPECT_THAT(run_times_, ::testing::ElementsAre(start_time + delay)); }; TEST_F(DeadlineTaskRunnerTest, RunTwice) { @@ -59,7 +59,7 @@ deadline_task_runner_->SetDeadline(FROM_HERE, delay2, clock_->NowTicks()); RunUntilIdle(); - EXPECT_THAT(run_times_, testing::ElementsAre(deadline1, deadline2)); + EXPECT_THAT(run_times_, ::testing::ElementsAre(deadline1, deadline2)); }; TEST_F(DeadlineTaskRunnerTest, EarlierDeadlinesTakePrecidence) { @@ -73,7 +73,7 @@ RunUntilIdle(); - EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay1)); + EXPECT_THAT(run_times_, ::testing::ElementsAre(start_time + delay1)); }; TEST_F(DeadlineTaskRunnerTest, LaterDeadlinesIgnored) { @@ -85,7 +85,7 @@ RunUntilIdle(); - EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay100)); + EXPECT_THAT(run_times_, ::testing::ElementsAre(start_time + delay100)); }; TEST_F(DeadlineTaskRunnerTest, DeleteDeadlineTaskRunnerAfterPosting) {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc index 14e62b43..e770040 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
@@ -30,7 +30,7 @@ estimation_percentile) {} }; -class IdleTimeEstimatorTest : public testing::Test { +class IdleTimeEstimatorTest : public ::testing::Test { public: IdleTimeEstimatorTest() : frame_length_(base::TimeDelta::FromMilliseconds(16)) {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc index 0894948..a07f183 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/render_widget_signals_unittest.cc
@@ -9,9 +9,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::AnyNumber; -using testing::Mock; -using testing::_; +using ::testing::AnyNumber; +using ::testing::Mock; +using ::testing::_; namespace blink { namespace scheduler { @@ -31,7 +31,7 @@ }; } -class RenderWidgetSignalsTest : public testing::Test { +class RenderWidgetSignalsTest : public ::testing::Test { public: RenderWidgetSignalsTest() {} ~RenderWidgetSignalsTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc index 9ac4a702..556ffba 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -256,7 +256,7 @@ return os << RendererSchedulerImpl::UseCaseToString(use_case); } -class RendererSchedulerImplTest : public testing::Test { +class RendererSchedulerImplTest : public ::testing::Test { public: using UseCase = RendererSchedulerImpl::UseCase; @@ -705,16 +705,16 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("D3"), std::string("D4"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("D3"), std::string("D4"))); } TEST_F(RendererSchedulerImplTest, TestPostDefaultAndCompositor) { std::vector<std::string> run_order; PostTestTasks(&run_order, "D1 C1"); RunUntilIdle(); - EXPECT_THAT(run_order, testing::Contains("D1")); - EXPECT_THAT(run_order, testing::Contains("C1")); + EXPECT_THAT(run_order, ::testing::Contains("D1")); + EXPECT_THAT(run_order, ::testing::Contains("C1")); } TEST_F(RendererSchedulerImplTest, TestRentrantTask) { @@ -726,7 +726,7 @@ &count, 5)); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4)); + EXPECT_THAT(run_order, ::testing::ElementsAre(0, 1, 2, 3, 4)); } TEST_F(RendererSchedulerImplTest, TestPostIdleTask) { @@ -854,9 +854,9 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("L1"), std::string("D1"), - std::string("D2"), std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("L1"), std::string("D1"), + std::string("D2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); } @@ -869,9 +869,9 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"), - std::string("C1"), std::string("D2"), - std::string("C2"), std::string("I1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"), + std::string("C1"), std::string("D2"), + std::string("C2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); } @@ -885,9 +885,9 @@ SimulateCompositorGestureStart(TouchEventPolicy::SEND_TOUCH_START); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"), - std::string("D2"), std::string("C1"), - std::string("C2"), std::string("I1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"), + std::string("D2"), std::string("C1"), + std::string("C2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -902,9 +902,9 @@ SimulateMainThreadGestureWithoutScrollUpdates(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("L1"), std::string("D1"), - std::string("D2"), std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("L1"), std::string("D1"), + std::string("D2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase()); } @@ -919,9 +919,9 @@ SimulateMainThreadGestureWithoutPreventDefault(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"), - std::string("D2"), std::string("C1"), - std::string("C2"), std::string("I1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"), + std::string("D2"), std::string("C1"), + std::string("C2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -952,9 +952,9 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("L1"), std::string("D1"), - std::string("D2"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("L1"), std::string("D1"), + std::string("D2"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -968,9 +968,9 @@ SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"), - std::string("D2"), std::string("C1"), - std::string("C2"), std::string("I1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"), + std::string("D2"), std::string("C1"), + std::string("C2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -986,9 +986,9 @@ blink::WebInputEvent::kGestureScrollBegin); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("L1"), std::string("D1"), - std::string("D2"), std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("L1"), std::string("D1"), + std::string("D2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase()); scheduler_->DidHandleInputEventOnMainThread( @@ -1006,9 +1006,9 @@ blink::WebInputEvent::kGestureScrollBegin); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("L1"), std::string("D1"), - std::string("D2"), std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("L1"), std::string("D1"), + std::string("D2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase()); scheduler_->DidHandleInputEventOnMainThread( @@ -1033,9 +1033,9 @@ // Because the main thread is performing custom input handling, we let all // tasks run. However compositing tasks are still given priority. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("L1"), std::string("D1"), - std::string("D2"), std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("L1"), std::string("D1"), + std::string("D2"), std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase()); } @@ -1058,9 +1058,9 @@ // Because we are still waiting for the touchstart to be processed, // non-essential tasks like loading tasks are blocked. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::TOUCHSTART, CurrentUseCase()); } @@ -1077,9 +1077,9 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("C1"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("C1"), std::string("C2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -1101,7 +1101,7 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("T1"))); + ::testing::ElementsAre(std::string("C1"), std::string("T1"))); } TEST_F(RendererSchedulerImplTest, @@ -1121,7 +1121,7 @@ EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_GESTURE, CurrentUseCase()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("C1"))); } TEST_F(RendererSchedulerImplTest, @@ -1142,7 +1142,7 @@ CurrentUseCase()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("T1"))); + ::testing::ElementsAre(std::string("C1"), std::string("T1"))); } TEST_F(RendererSchedulerImplTest, @@ -1163,7 +1163,7 @@ CurrentUseCase()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("T1"))); + ::testing::ElementsAre(std::string("C1"), std::string("T1"))); } TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_Compositor) { @@ -1178,8 +1178,8 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"))); // Animation or meta events like TapDown/FlingCancel shouldn't affect the // priority. @@ -1192,7 +1192,7 @@ FakeInputEvent(blink::WebInputEvent::kGestureTapDown), RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); // Action events like ScrollBegin will kick us back into compositor priority, // allowing service of the timer, loading and idle queues. @@ -1203,8 +1203,8 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("T1"), - std::string("T2"))); + ::testing::ElementsAre(std::string("L1"), std::string("T1"), + std::string("T2"))); } TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_MainThread) { @@ -1222,8 +1222,8 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"))); // Meta events like TapDown/FlingCancel shouldn't affect the priority. run_order.clear(); @@ -1240,7 +1240,7 @@ FakeInputEvent(blink::WebInputEvent::kGestureTapDown), WebInputEventResult::kHandledSystem); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); // Action events like ScrollBegin will kick us back into compositor priority, // allowing service of the timer, loading and idle queues. @@ -1254,8 +1254,8 @@ RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("T1"), - std::string("T2"))); + ::testing::ElementsAre(std::string("L1"), std::string("T1"), + std::string("T2"))); } // TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase. @@ -1272,7 +1272,7 @@ std::string("D1"), std::string("L1"), std::string("D2"), std::string("L2"), std::string("C1"), std::string("T1"), std::string("C2"), std::string("T2"), std::string("I1")}; - EXPECT_THAT(run_order, testing::ElementsAreArray(loading_policy_expected)); + EXPECT_THAT(run_order, ::testing::ElementsAreArray(loading_policy_expected)); EXPECT_EQ(RendererSchedulerImpl::UseCase::LOADING, CurrentUseCase()); // Advance 15s and try again, the loading policy should have ended and the @@ -1288,7 +1288,7 @@ std::string("D1"), std::string("C1"), std::string("T1"), std::string("L1"), std::string("D2"), std::string("C2"), std::string("T2"), std::string("L2"), std::string("I1")}; - EXPECT_THAT(run_order, testing::ElementsAreArray(default_order_expected)); + EXPECT_THAT(run_order, ::testing::ElementsAreArray(default_order_expected)); EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); } @@ -1307,9 +1307,9 @@ // Note compositor tasks are not prioritized. EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("C1"), - std::string("D2"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("C1"), + std::string("D2"), std::string("C2"), + std::string("I1"))); } TEST_F(RendererSchedulerImplTest, @@ -1327,9 +1327,9 @@ // Note compositor tasks are not prioritized. EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("C1"), - std::string("D2"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("C1"), + std::string("D2"), std::string("C2"), + std::string("I1"))); } TEST_F(RendererSchedulerImplTest, @@ -1349,9 +1349,9 @@ EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("C1"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("C1"), std::string("C2"), + std::string("I1"))); } TEST_F(RendererSchedulerImplTest, @@ -1367,9 +1367,9 @@ RunUntilIdle(); // Note compositor tasks are prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"), + std::string("I1"))); scheduler_->DidHandleInputEventOnMainThread( FakeInputEvent(blink::WebInputEvent::kMouseMove, blink::WebInputEvent::kLeftButtonDown), @@ -1407,9 +1407,9 @@ // Note compositor tasks are prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"), + std::string("I1"))); } TEST_F(RendererSchedulerImplTest, @@ -1436,9 +1436,9 @@ // Note compositor tasks are prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"), + std::string("I1"))); } TEST_F(RendererSchedulerImplTest, EventConsumedOnCompositorThread_MouseWheel) { @@ -1452,9 +1452,9 @@ RunUntilIdle(); // Note compositor tasks are not prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("C1"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("C1"), std::string("C2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -1471,9 +1471,9 @@ RunUntilIdle(); // Note compositor tasks are prioritized (since they are fast). EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING, CurrentUseCase()); } @@ -1498,9 +1498,9 @@ RunUntilIdle(); // Note compositor tasks are prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_GESTURE, CurrentUseCase()); } @@ -1527,9 +1527,9 @@ RunUntilIdle(); // Note compositor tasks are not prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("D2"), - std::string("C1"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("D2"), + std::string("C1"), std::string("C2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); } @@ -1548,9 +1548,9 @@ RunUntilIdle(); // Note compositor tasks are not prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("C1"), - std::string("D2"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("C1"), + std::string("D2"), std::string("C2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); } @@ -1568,9 +1568,9 @@ RunUntilIdle(); // Note compositor tasks are not prioritized. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D1"), std::string("C1"), - std::string("D2"), std::string("C2"), - std::string("I1"))); + ::testing::ElementsAre(std::string("D1"), std::string("C1"), + std::string("D2"), std::string("C2"), + std::string("I1"))); EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase()); // Note compositor tasks are not prioritized. scheduler_->DidHandleInputEventOnMainThread( @@ -1599,8 +1599,8 @@ // Ensure that the default D1 task gets to run at some point before the final // C2 compositor task. EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("D1"), - std::string("C2"))); + ::testing::ElementsAre(std::string("C1"), std::string("D1"), + std::string("C2"))); } TEST_F(RendererSchedulerImplTest, @@ -1633,8 +1633,8 @@ RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"))); run_order.clear(); clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); @@ -1646,8 +1646,8 @@ // Touchstart policy mode should have ended now that the clock has advanced. RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"), - std::string("D2"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"), + std::string("D2"))); } TEST_F(RendererSchedulerImplTest, @@ -1661,8 +1661,8 @@ RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("C2"), - std::string("D1"), std::string("D2"))); + ::testing::ElementsAre(std::string("C1"), std::string("C2"), + std::string("D1"), std::string("D2"))); // Receiving the first touchmove will not affect scheduler priority. run_order.clear(); @@ -1670,7 +1670,7 @@ FakeInputEvent(blink::WebInputEvent::kTouchMove), RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); // Receiving the second touchmove will kick us back into compositor priority. run_order.clear(); @@ -1678,7 +1678,7 @@ FakeInputEvent(blink::WebInputEvent::kTouchMove), RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("L1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("L1"))); } TEST_F(RendererSchedulerImplTest, TestIsHighPriorityWorkAnticipated) { @@ -2044,7 +2044,7 @@ RunUntilIdle(); EXPECT_THAT( mock_scheduler_->use_cases_, - testing::ElementsAre( + ::testing::ElementsAre( std::string("none"), std::string("compositor_gesture"), std::string("compositor_gesture touchstart expected"), std::string("none touchstart expected"), std::string("none"))); @@ -2106,9 +2106,9 @@ EnableIdleTasks(); RunUntilIdle(); // Note we expect task 3 to run last because it's non-nestable. - EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"), - std::string("4"), std::string("5"), - std::string("3"))); + EXPECT_THAT(order, ::testing::ElementsAre(std::string("1"), std::string("2"), + std::string("4"), std::string("5"), + std::string("3"))); } TEST_F(RendererSchedulerImplTest, TestBeginMainFrameNotExpectedUntil) { @@ -2213,7 +2213,7 @@ EXPECT_EQ(3, run_count); EXPECT_THAT( actual_deadlines, - testing::ElementsAre( + ::testing::ElementsAre( clock_before + maximum_idle_period_duration(), clock_before + idle_task_runtime + maximum_idle_period_duration(), clock_before + (2 * idle_task_runtime) + @@ -2351,7 +2351,7 @@ PostTestTasks(&run_order, "T1 T2"); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("T1"), std::string("T2"))); + ::testing::ElementsAre(std::string("T1"), std::string("T2"))); } TEST_F(RendererSchedulerImplTest, SuspendAndResumeTimerQueue) { @@ -2360,12 +2360,12 @@ scheduler_->SuspendTimerQueue(); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); scheduler_->ResumeTimerQueue(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("T1"), std::string("T2"))); + ::testing::ElementsAre(std::string("T1"), std::string("T2"))); } TEST_F(RendererSchedulerImplTest, SuspendAndThrottleTimerQueue) { @@ -2377,7 +2377,7 @@ scheduler_->task_queue_throttler()->IncreaseThrottleRefCount( static_cast<TaskQueue*>(timer_task_runner_.get())); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); } TEST_F(RendererSchedulerImplTest, ThrottleAndSuspendTimerQueue) { @@ -2389,7 +2389,7 @@ RunUntilIdle(); scheduler_->SuspendTimerQueue(); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); } TEST_F(RendererSchedulerImplTest, MultipleSuspendsNeedMultipleResumes) { @@ -2400,20 +2400,20 @@ scheduler_->SuspendTimerQueue(); scheduler_->SuspendTimerQueue(); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); scheduler_->ResumeTimerQueue(); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); scheduler_->ResumeTimerQueue(); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); scheduler_->ResumeTimerQueue(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("T1"), std::string("T2"))); + ::testing::ElementsAre(std::string("T1"), std::string("T2"))); } TEST_F(RendererSchedulerImplTest, SuspendRenderer) { @@ -2427,15 +2427,15 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("D1"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("D1"), + std::string("I1"))); // The rest queued tasks fire when the tab goes foregrounded. run_order.clear(); scheduler_->SetRendererBackgrounded(false); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("T1"))); + ::testing::ElementsAre(std::string("L1"), std::string("T1"))); run_order.clear(); PostTestTasks(&run_order, "D2 T2"); @@ -2443,7 +2443,7 @@ scheduler_->SuspendRenderer(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D2"), std::string("T2"))); + ::testing::ElementsAre(std::string("D2"), std::string("T2"))); } TEST_F(RendererSchedulerImplTest, ResumeRenderer) { @@ -2459,15 +2459,15 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("D1"), - std::string("I1"))); + ::testing::ElementsAre(std::string("C1"), std::string("D1"), + std::string("I1"))); // The rest queued tasks fire when the renderer is resumed. run_order.clear(); scheduler_->ResumeRenderer(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("T1"))); + ::testing::ElementsAre(std::string("L1"), std::string("T1"))); run_order.clear(); // No crash occurs when the renderer is suspended again, and @@ -2477,15 +2477,15 @@ EnableIdleTasks(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C2"), std::string("D2"), - std::string("I2"))); + ::testing::ElementsAre(std::string("C2"), std::string("D2"), + std::string("I2"))); // The rest queued tasks fire when the renderer is resumed. run_order.clear(); scheduler_->ResumeRenderer(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L2"), std::string("T2"))); + ::testing::ElementsAre(std::string("L2"), std::string("T2"))); run_order.clear(); PostTestTasks(&run_order, "D3 T3"); @@ -2494,7 +2494,7 @@ scheduler_->SetRendererBackgrounded(false); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D3"), std::string("T3"))); + ::testing::ElementsAre(std::string("D3"), std::string("T3"))); run_order.clear(); PostTestTasks(&run_order, "D4 T4"); @@ -2502,7 +2502,7 @@ scheduler_->ResumeRenderer(); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("D4"), std::string("T4"))); + ::testing::ElementsAre(std::string("D4"), std::string("T4"))); } TEST_F(RendererSchedulerImplTest, UseCaseToString) { @@ -2539,7 +2539,7 @@ std::vector<std::string> run_order; PostTestTasks(&run_order, "D1 C1"); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); } TEST_F(RendererSchedulerImplTest, TestRendererBackgroundedTimerSuspension) { @@ -2556,7 +2556,7 @@ clock_->SetNowTicks(now); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("T1"), std::string("T2"))); + ::testing::ElementsAre(std::string("T1"), std::string("T2"))); run_order.clear(); PostTestTasks(&run_order, "T3"); @@ -2564,7 +2564,7 @@ now += base::TimeDelta::FromSeconds(1); clock_->SetNowTicks(now); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("T3"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("T3"))); // Advance the time until after the scheduled timer queue suspension. now = base::TimeTicks() + suspend_timers_when_backgrounded_delay() + @@ -2579,18 +2579,18 @@ now += base::TimeDelta::FromSeconds(10); clock_->SetNowTicks(now); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); + EXPECT_THAT(run_order, ::testing::ElementsAre()); scheduler_->SetRendererBackgrounded(false); RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("T4"), std::string("T5"))); + ::testing::ElementsAre(std::string("T4"), std::string("T5"))); // Subsequent timer tasks should fire as usual. run_order.clear(); PostTestTasks(&run_order, "T6"); RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("T6"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("T6"))); } TEST_F(RendererSchedulerImplTest, @@ -2609,7 +2609,7 @@ EXPECT_FALSE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"))); // Emit a BeginMainFrame, and the loading task should get blocked. DoMainFrame(); @@ -2623,7 +2623,7 @@ EXPECT_TRUE(LoadingTasksSeemExpensive()); EXPECT_FALSE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2644,7 +2644,7 @@ EXPECT_FALSE(TimerTasksSeemExpensive()); EXPECT_FALSE(TouchStartExpectedSoon()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode()); } @@ -2665,7 +2665,7 @@ EXPECT_FALSE(LoadingTasksSeemExpensive()); EXPECT_TRUE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2701,7 +2701,7 @@ EXPECT_TRUE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("T1"), std::string("D1"))); + ::testing::ElementsAre(std::string("T1"), std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode()); } @@ -2724,7 +2724,7 @@ EXPECT_FALSE(LoadingTasksSeemExpensive()); EXPECT_TRUE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2746,7 +2746,7 @@ EXPECT_FALSE(LoadingTasksSeemExpensive()); EXPECT_TRUE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2765,7 +2765,7 @@ RunUntilIdle(); // The expensive loading task gets blocked. - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2790,7 +2790,7 @@ EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_EQ(1, NavigationTaskExpectedCount()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"))); // After the nagigation has been cancelled, the expensive loading tasks should // get blocked. @@ -2807,7 +2807,7 @@ EXPECT_FALSE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_EQ(0, NavigationTaskExpectedCount()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2834,7 +2834,7 @@ EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_EQ(2, NavigationTaskExpectedCount()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"))); run_order.clear(); scheduler_->RemovePendingNavigation( @@ -2851,7 +2851,7 @@ EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_EQ(1, NavigationTaskExpectedCount()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("L1"), std::string("D1"))); + ::testing::ElementsAre(std::string("L1"), std::string("D1"))); run_order.clear(); scheduler_->RemovePendingNavigation( @@ -2867,7 +2867,7 @@ EXPECT_FALSE(TimerTasksSeemExpensive()); EXPECT_TRUE(TouchStartExpectedSoon()); EXPECT_EQ(0, NavigationTaskExpectedCount()); - EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); + EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("D1"))); EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode()); } @@ -2890,7 +2890,7 @@ EXPECT_TRUE(LoadingTasksSeemExpensive()); EXPECT_FALSE(TimerTasksSeemExpensive()); EXPECT_THAT(run_order, - testing::ElementsAre(std::string("C1"), std::string("L1"))); + ::testing::ElementsAre(std::string("C1"), std::string("L1"))); EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode()); } @@ -3864,8 +3864,9 @@ mock_task_runner_->RunUntilTime(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1100)); - EXPECT_THAT(run_times, testing::ElementsAre(base::TimeTicks() + - base::TimeDelta::FromSeconds(1))); + EXPECT_THAT(run_times, + ::testing::ElementsAre(base::TimeTicks() + + base::TimeDelta::FromSeconds(1))); run_times.clear(); timer_task_runner_->PostDelayedTask( @@ -3878,8 +3879,8 @@ base::TimeDelta::FromMilliseconds(1500)); EXPECT_THAT(run_times, - testing::ElementsAre(base::TimeTicks() + - base::TimeDelta::FromMilliseconds(1300))); + ::testing::ElementsAre(base::TimeTicks() + + base::TimeDelta::FromMilliseconds(1300))); } TEST_F(RendererSchedulerImplTest, UnresponsiveMainThread) {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_cost_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_cost_estimator_unittest.cc index 478fc98d..bf32311 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/task_cost_estimator_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_cost_estimator_unittest.cc
@@ -14,7 +14,7 @@ namespace blink { namespace scheduler { -class TaskCostEstimatorTest : public testing::Test { +class TaskCostEstimatorTest : public ::testing::Test { public: TaskCostEstimatorTest() {} ~TaskCostEstimatorTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_duration_metric_reporter_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_duration_metric_reporter_unittest.cc index 52eba2a6..4e7a63f 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/task_duration_metric_reporter_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_duration_metric_reporter_unittest.cc
@@ -16,8 +16,8 @@ namespace { -using testing::_; -using testing::Mock; +using ::testing::_; +using ::testing::Mock; class FakeHistogram : public base::HistogramBase { public:
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc index d4aa08f9..cd39aa3 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
@@ -25,7 +25,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::ElementsAre; +using ::testing::ElementsAre; namespace { bool MessageLoopTaskCounter(size_t* count) { @@ -85,7 +85,7 @@ } // namespace -class TaskQueueThrottlerTest : public testing::Test { +class TaskQueueThrottlerTest : public ::testing::Test { public: TaskQueueThrottlerTest() {} ~TaskQueueThrottlerTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/user_model_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/user_model_unittest.cc index 4c8592f..bfa2e34 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/user_model_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/user_model_unittest.cc
@@ -11,7 +11,7 @@ namespace blink { namespace scheduler { -class UserModelTest : public testing::Test { +class UserModelTest : public ::testing::Test { public: UserModelTest() {} ~UserModelTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc index b0d55fbd..1769afc 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
@@ -22,7 +22,7 @@ namespace blink { namespace scheduler { -class WebFrameSchedulerImplTest : public testing::Test { +class WebFrameSchedulerImplTest : public ::testing::Test { public: WebFrameSchedulerImplTest() {} ~WebFrameSchedulerImplTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc index 25524888..7ebaf18 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -23,13 +23,13 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::ElementsAre; +using ::testing::ElementsAre; using VirtualTimePolicy = blink::WebViewScheduler::VirtualTimePolicy; namespace blink { namespace scheduler { -class WebViewSchedulerImplTest : public testing::Test { +class WebViewSchedulerImplTest : public ::testing::Test { public: WebViewSchedulerImplTest() {} ~WebViewSchedulerImplTest() override {}
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc index f57a222..b09a7fb 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -39,7 +39,7 @@ }; } // namespace -class WebThreadImplForRendererSchedulerTest : public testing::Test { +class WebThreadImplForRendererSchedulerTest : public ::testing::Test { public: WebThreadImplForRendererSchedulerTest() {} @@ -77,7 +77,7 @@ MockTask task; { - testing::InSequence sequence; + ::testing::InSequence sequence; EXPECT_CALL(observer, WillProcessTask()); EXPECT_CALL(task, Run()); EXPECT_CALL(observer, DidProcessTask()); @@ -96,7 +96,7 @@ SetWorkBatchSizeForTesting(kWorkBatchSize); { - testing::InSequence sequence; + ::testing::InSequence sequence; EXPECT_CALL(observer, WillProcessTask()); EXPECT_CALL(task, Run()); EXPECT_CALL(observer, DidProcessTask()); @@ -116,7 +116,7 @@ SetWorkBatchSizeForTesting(kWorkBatchSize); { - testing::InSequence sequence; + ::testing::InSequence sequence; EXPECT_CALL(observer, WillProcessTask()); EXPECT_CALL(task1, Run()); EXPECT_CALL(observer, DidProcessTask()); @@ -143,7 +143,7 @@ SetWorkBatchSizeForTesting(kWorkBatchSize); { - testing::InSequence sequence; + ::testing::InSequence sequence; EXPECT_CALL(observer, WillProcessTask()); EXPECT_CALL(task1, Run()); EXPECT_CALL(observer, DidProcessTask()); @@ -183,7 +183,7 @@ thread_->AddTaskObserver(&observer); { - testing::InSequence sequence; + ::testing::InSequence sequence; // One callback for EnterRunLoop. EXPECT_CALL(observer, WillProcessTask());
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp index f2134c9..950fb14 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
@@ -39,9 +39,9 @@ namespace blink { -using testing::AtLeast; -using testing::Return; -using testing::_; +using ::testing::AtLeast; +using ::testing::Return; +using ::testing::_; static double g_mocked_time = 0.0;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp index 12e17d7..1c3d244 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
@@ -20,8 +20,8 @@ namespace { -using testing::_; -using testing::Return; +using ::testing::_; +using ::testing::Return; class ScrollbarThemeWithMockInvalidation : public ScrollbarThemeMock { public: @@ -32,7 +32,7 @@ } // namespace -using ScrollableAreaTest = testing::Test; +using ScrollableAreaTest = ::testing::Test; TEST_F(ScrollableAreaTest, ScrollAnimatorCurrentPositionShouldBeSync) { ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeAuraTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeAuraTest.cpp index 591da78f..e877aa9 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeAuraTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeAuraTest.cpp
@@ -9,7 +9,7 @@ namespace blink { -using testing::Return; +using ::testing::Return; namespace { @@ -29,7 +29,7 @@ } // namespace -using ScrollbarThemeAuraTest = testing::Test; +using ScrollbarThemeAuraTest = ::testing::Test; TEST_F(ScrollbarThemeAuraTest, ButtonSizeHorizontal) { ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp index 7beab665..af00cb4 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp
@@ -9,10 +9,10 @@ namespace blink { -using testing::NiceMock; -using testing::Return; +using ::testing::NiceMock; +using ::testing::Return; -using ScrollbarThemeOverlayTest = testing::Test; +using ScrollbarThemeOverlayTest = ::testing::Test; TEST_F(ScrollbarThemeOverlayTest, PaintInvalidation) { ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
diff --git a/third_party/WebKit/Source/platform/testing/CompositorTest.h b/third_party/WebKit/Source/platform/testing/CompositorTest.h index d0e3008b..0a460fc 100644 --- a/third_party/WebKit/Source/platform/testing/CompositorTest.h +++ b/third_party/WebKit/Source/platform/testing/CompositorTest.h
@@ -13,7 +13,7 @@ namespace blink { -class CompositorTest : public testing::Test { +class CompositorTest : public ::testing::Test { WTF_MAKE_NONCOPYABLE(CompositorTest); public:
diff --git a/third_party/WebKit/Source/platform/text/CharacterTest.cpp b/third_party/WebKit/Source/platform/text/CharacterTest.cpp index 55f07d7..55e4c68 100644 --- a/third_party/WebKit/Source/platform/text/CharacterTest.cpp +++ b/third_party/WebKit/Source/platform/text/CharacterTest.cpp
@@ -9,18 +9,19 @@ namespace blink { -testing::AssertionResult IsCJKIdeographOrSymbolWithMessage(UChar32 codepoint) { +::testing::AssertionResult IsCJKIdeographOrSymbolWithMessage( + UChar32 codepoint) { const size_t kFormatBufferSize = 10; char formatted_as_hex[kFormatBufferSize]; snprintf(formatted_as_hex, kFormatBufferSize, "0x%x", codepoint); if (Character::IsCJKIdeographOrSymbol(codepoint)) { - return testing::AssertionSuccess() + return ::testing::AssertionSuccess() << "Codepoint " << formatted_as_hex << " is a CJKIdeographOrSymbol."; } - return testing::AssertionFailure() << "Codepoint " << formatted_as_hex - << " is not a CJKIdeographOrSymbol."; + return ::testing::AssertionFailure() << "Codepoint " << formatted_as_hex + << " is not a CJKIdeographOrSymbol."; } TEST(CharacterTest, HammerEmojiVsCJKIdeographOrSymbol) {
diff --git a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp index 3f9071a..9c54bac 100644 --- a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp +++ b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
@@ -6,6 +6,7 @@ #include "build/build_config.h" #include "platform/LayoutLocale.h" +#include "platform/fonts/FontGlobalContext.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_ANDROID) @@ -31,7 +32,7 @@ LayoutLocale::SetHyphenationForTesting("en-UK", nullptr); EXPECT_EQ(nullptr, LayoutLocale::Get("en-UK")->GetHyphenation()); - LayoutLocale::ClearForTesting(); + FontGlobalContext::ClearForTesting(); } #if defined(OS_ANDROID) || defined(OS_MACOSX)
diff --git a/third_party/WebKit/Source/platform/text/PlatformLocale.cpp b/third_party/WebKit/Source/platform/text/PlatformLocale.cpp index 4f97a11..e69e325 100644 --- a/third_party/WebKit/Source/platform/text/PlatformLocale.cpp +++ b/third_party/WebKit/Source/platform/text/PlatformLocale.cpp
@@ -37,6 +37,10 @@ namespace blink { +namespace { +Locale* g_default_locale; +} + class DateTimeStringBuilder : private DateTimeFormat::TokenHandler { WTF_MAKE_NONCOPYABLE(DateTimeStringBuilder); @@ -176,9 +180,17 @@ } Locale& Locale::DefaultLocale() { - static Locale* locale = Locale::Create(DefaultLanguage()).release(); DCHECK(IsMainThread()); - return *locale; + if (!g_default_locale) + g_default_locale = Locale::Create(DefaultLanguage()).release(); + return *g_default_locale; +} + +void Locale::ResetDefautlLocale() { + // This is safe because no one owns a Locale object returned by + // DefaultLocale(). + delete g_default_locale; + g_default_locale = nullptr; } Locale::~Locale() {}
diff --git a/third_party/WebKit/Source/platform/text/PlatformLocale.h b/third_party/WebKit/Source/platform/text/PlatformLocale.h index 96ce6e9..8649c51 100644 --- a/third_party/WebKit/Source/platform/text/PlatformLocale.h +++ b/third_party/WebKit/Source/platform/text/PlatformLocale.h
@@ -42,6 +42,7 @@ public: static std::unique_ptr<Locale> Create(const String& locale_identifier); static Locale& DefaultLocale(); + static void ResetDefautlLocale(); String QueryString(WebLocalizedString::Name); String QueryString(WebLocalizedString::Name, const String& parameter);
diff --git a/third_party/WebKit/Source/platform/text/TextBreakIteratorTest.cpp b/third_party/WebKit/Source/platform/text/TextBreakIteratorTest.cpp index 0a322f0..3d407033 100644 --- a/third_party/WebKit/Source/platform/text/TextBreakIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/text/TextBreakIteratorTest.cpp
@@ -10,7 +10,7 @@ namespace blink { -class TextBreakIteratorTest : public testing::Test { +class TextBreakIteratorTest : public ::testing::Test { protected: void SetTestString(const char* test_string) { test_string_ = String::FromUTF8(test_string); @@ -40,7 +40,7 @@ break_positions.push_back(i); } EXPECT_THAT(break_positions, - testing::ElementsAreArray(expected_break_positions)) + ::testing::ElementsAreArray(expected_break_positions)) << break_iterator.BreakType() << " for " << test_string_; } @@ -54,7 +54,7 @@ break_positions.push_back(i); } EXPECT_THAT(break_positions, - testing::ElementsAreArray(expected_break_positions)) + ::testing::ElementsAreArray(expected_break_positions)) << break_iterator.BreakType() << " for " << test_string_; }
diff --git a/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp b/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp index ce3d933..b8c10eec 100644 --- a/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp +++ b/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp
@@ -143,8 +143,8 @@ platform->SetPublicSuffix("com"); for (const auto& test : inputs) { - SCOPED_TRACE(testing::Message() << "Host: " << test.host - << ", Origin: " << test.origin); + SCOPED_TRACE(::testing::Message() + << "Host: " << test.host << ", Origin: " << test.origin); RefPtr<SecurityOrigin> origin_to_test = SecurityOrigin::CreateFromString(test.origin); OriginAccessEntry entry1(test.protocol, test.host, @@ -202,7 +202,7 @@ OriginAccessEntry entry1(test.protocol, test.host, OriginAccessEntry::kAllowRegisterableDomains); - SCOPED_TRACE(testing::Message() + SCOPED_TRACE(::testing::Message() << "Host: " << test.host << ", Origin: " << test.origin << ", Domain: " << entry1.Registerable().Utf8().data()); EXPECT_EQ(test.expected, entry1.MatchesOrigin(*origin_to_test)); @@ -258,7 +258,7 @@ OriginAccessEntry entry1(test.protocol, test.host, OriginAccessEntry::kAllowRegisterableDomains); - SCOPED_TRACE(testing::Message() + SCOPED_TRACE(::testing::Message() << "Host: " << test.host << ", Origin: " << test.origin << ", Domain: " << entry1.Registerable().Utf8().data()); EXPECT_EQ(test.expected, entry1.MatchesOrigin(*origin_to_test)); @@ -304,8 +304,8 @@ platform->SetPublicSuffix("com"); for (const auto& test : inputs) { - SCOPED_TRACE(testing::Message() << "Host: " << test.host - << ", Origin: " << test.origin); + SCOPED_TRACE(::testing::Message() + << "Host: " << test.host << ", Origin: " << test.origin); RefPtr<SecurityOrigin> origin_to_test = SecurityOrigin::CreateFromString(test.origin); OriginAccessEntry entry1(test.protocol, test.host, @@ -335,7 +335,7 @@ platform->SetPublicSuffix("com"); for (const auto& test : inputs) { - SCOPED_TRACE(testing::Message() << "Host: " << test.host); + SCOPED_TRACE(::testing::Message() << "Host: " << test.host); OriginAccessEntry entry(test.protocol, test.host, OriginAccessEntry::kDisallowSubdomains); EXPECT_EQ(test.is_ip_address, entry.HostIsIPAddress()) << test.host; @@ -363,8 +363,8 @@ platform->SetPublicSuffix("com"); for (const auto& test : inputs) { - SCOPED_TRACE(testing::Message() << "Host: " << test.host - << ", Origin: " << test.origin); + SCOPED_TRACE(::testing::Message() + << "Host: " << test.host << ", Origin: " << test.origin); RefPtr<SecurityOrigin> origin_to_test = SecurityOrigin::CreateFromString(test.origin); OriginAccessEntry entry1(test.protocol, test.host,
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp index 81b1f2c6..5a0012a 100644 --- a/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp +++ b/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
@@ -516,7 +516,7 @@ }; for (const TestCase& test : cases) { - SCOPED_TRACE(testing::Message() << "raw host: '" << test.host << "'"); + SCOPED_TRACE(::testing::Message() << "raw host: '" << test.host << "'"); String host = String::FromUTF8(test.host); bool success = false; String canonical_host = SecurityOrigin::CanonicalizeHost(host, &success);
diff --git a/third_party/WebKit/Source/web/WebKit.cpp b/third_party/WebKit/Source/web/WebKit.cpp index b0df44c..169c52447 100644 --- a/third_party/WebKit/Source/web/WebKit.cpp +++ b/third_party/WebKit/Source/web/WebKit.cpp
@@ -88,6 +88,7 @@ void ResetPluginCache(bool reload_pages) { DCHECK(!reload_pages); Page::RefreshPlugins(); + Page::ResetPluginData(); } void DecommitFreeableMemory() {
diff --git a/third_party/WebKit/Source/web/tests/AccessibilityObjectModelTest.cpp b/third_party/WebKit/Source/web/tests/AccessibilityObjectModelTest.cpp index 1622da19..ac9a4f6 100644 --- a/third_party/WebKit/Source/web/tests/AccessibilityObjectModelTest.cpp +++ b/third_party/WebKit/Source/web/tests/AccessibilityObjectModelTest.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "core/dom/AccessibleNode.h" +#include "core/dom/AccessibleNodeList.h" #include "core/html/HTMLBodyElement.h" #include "core/testing/sim/SimRequest.h" #include "core/testing/sim/SimTest.h" @@ -342,6 +343,41 @@ ->RoleValue()); } +TEST_F(AccessibilityObjectModelTest, LabeledBy) { + SimRequest main_resource("https://example.com/", "text/html"); + LoadURL("https://example.com/"); + main_resource.Complete( + "<input id=target aria-labelledby='l1 l2'>" + "<label id=l1>Label 1</label>" + "<label id=l2>Label 2</label>" + "<label id=l3>Label 3</label>"); + + auto* target = GetDocument().getElementById("target"); + auto* l1 = GetDocument().getElementById("l1"); + auto* l2 = GetDocument().getElementById("l2"); + auto* l3 = GetDocument().getElementById("l3"); + + HeapVector<Member<Element>> labeled_by; + ASSERT_TRUE(AccessibleNode::GetPropertyOrARIAAttribute( + target, AOMRelationListProperty::kLabeledBy, labeled_by)); + ASSERT_EQ(2U, labeled_by.size()); + ASSERT_EQ(l1, labeled_by[0]); + ASSERT_EQ(l2, labeled_by[1]); + + AccessibleNodeList* node_list = target->accessibleNode()->labeledBy(); + ASSERT_EQ(nullptr, node_list); + + node_list = new AccessibleNodeList(); + node_list->add(l3->accessibleNode()); + target->accessibleNode()->setLabeledBy(node_list); + + labeled_by.clear(); + ASSERT_TRUE(AccessibleNode::GetPropertyOrARIAAttribute( + target, AOMRelationListProperty::kLabeledBy, labeled_by)); + ASSERT_EQ(1U, labeled_by.size()); + ASSERT_EQ(l3, labeled_by[0]); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/ChromeClientImplTest.cpp b/third_party/WebKit/Source/web/tests/ChromeClientImplTest.cpp index 801ea595..b9877cb7 100644 --- a/third_party/WebKit/Source/web/tests/ChromeClientImplTest.cpp +++ b/third_party/WebKit/Source/web/tests/ChromeClientImplTest.cpp
@@ -80,7 +80,7 @@ FrameTestHelpers::WebViewHelper web_view_helper_; }; -class CreateWindowTest : public testing::Test { +class CreateWindowTest : public ::testing::Test { protected: void SetUp() override { web_view_ = helper_.Initialize(nullptr, &web_view_client_); @@ -161,7 +161,7 @@ Member<Element> owner_element_; }; -class PagePopupSuppressionTest : public testing::Test { +class PagePopupSuppressionTest : public ::testing::Test { public: PagePopupSuppressionTest() {}
diff --git a/third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp b/third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp index 5f4cb67b..6e1569e 100644 --- a/third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp +++ b/third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp
@@ -41,9 +41,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; -using testing::Mock; -using testing::Return; +using ::testing::_; +using ::testing::Mock; +using ::testing::Return; namespace blink { namespace {
diff --git a/third_party/WebKit/Source/web/tests/ScrollMetricsTest.cpp b/third_party/WebKit/Source/web/tests/ScrollMetricsTest.cpp index be96ff5..10ec3a8 100644 --- a/third_party/WebKit/Source/web/tests/ScrollMetricsTest.cpp +++ b/third_party/WebKit/Source/web/tests/ScrollMetricsTest.cpp
@@ -319,11 +319,10 @@ " .box { overflow:scroll; width: 100px; height: 100px; }" " .translucent { opacity: 0.5; }" " .transform { transform: scale(0.8); }" - " .with-border-radius { border: 5px solid; border-radius: 5px; }" " .spacer { height: 1000px; }" " .composited { will-change: transform; }" "</style>" - "<div id='container' class='container with-border-radius'>" + "<div id='container' class='container'>" " <div class='translucent box'>" " <div id='inner' class='composited transform box'>" " <div class='spacer'></div>" @@ -348,9 +347,8 @@ EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); EXPECT_WHEEL_BUCKET(kIsNotStackingContextAndLCDText, 1); - EXPECT_WHEEL_BUCKET(kHasBorderRadius, 1); EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 0); - EXPECT_WHEEL_TOTAL(4); + EXPECT_WHEEL_TOTAL(3); } } // namespace
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index 7e779df..a33f94d 100644 --- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -168,9 +168,9 @@ using blink::URLTestHelpers::ToKURL; using blink::testing::RunPendingTasks; -using testing::ElementsAre; -using testing::Mock; -using testing::_; +using ::testing::ElementsAre; +using ::testing::Mock; +using ::testing::_; namespace blink {
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index a7b56c5..6b9fb39f 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -338,6 +338,7 @@ "platform/WebStorageQuotaError.h", "platform/WebStorageQuotaType.h", "platform/WebString.h", + "platform/WebSurfaceLayerBridge.h", "platform/WebTextInputInfo.h", "platform/WebTextInputMode.h", "platform/WebTextInputType.h",
diff --git a/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h b/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h new file mode 100644 index 0000000..10be3a6 --- /dev/null +++ b/third_party/WebKit/public/platform/WebSurfaceLayerBridge.h
@@ -0,0 +1,22 @@ +// 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 WebSurfaceLayerBridge_h +#define WebSurfaceLayerBridge_h + +#include "WebCommon.h" +#include "WebLayer.h" + +namespace blink { + +// Maintains and exposes the SurfaceLayer. +class BLINK_PLATFORM_EXPORT WebSurfaceLayerBridge { + public: + static WebSurfaceLayerBridge* Create(); + virtual WebLayer* GetWebLayer() const = 0; +}; + +} // namespace blink + +#endif // WebSurfaceLayerBridge_h
diff --git a/third_party/WebKit/public/web/WebKit.h b/third_party/WebKit/public/web/WebKit.h index 95f4d32..d130be3 100644 --- a/third_party/WebKit/public/web/WebKit.h +++ b/third_party/WebKit/public/web/WebKit.h
@@ -60,8 +60,9 @@ BLINK_EXPORT void SetFontAntialiasingEnabledForTest(bool); BLINK_EXPORT bool FontAntialiasingEnabledForTest(); -// Purge the plugin list cache. If |reloadPages| is true, any pages -// containing plugins will be reloaded after refreshing the plugin list. +// Purge the plugin list cache. This can cause a web-visible and out-of-spec +// change to |navigator.plugins| if the plugin list has changed (see +// https://crbug.com/735854). |reloadPages| is unsupported and must be false. BLINK_EXPORT void ResetPluginCache(bool reload_pages = false); // The embedder should call this periodically in an attempt to balance overall
diff --git a/third_party/khronos/EGL/eglplatform.h b/third_party/khronos/EGL/eglplatform.h index dfbc52ce..fad491b 100644 --- a/third_party/khronos/EGL/eglplatform.h +++ b/third_party/khronos/EGL/eglplatform.h
@@ -77,7 +77,7 @@ typedef HBITMAP EGLNativePixmapType; typedef HWND EGLNativeWindowType; -#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) || defined(__Fuchsia__) typedef int EGLNativeDisplayType; typedef void *EGLNativeWindowType;
diff --git a/third_party/khronos/README.chromium b/third_party/khronos/README.chromium index 83eaa5a2..e6b667f8 100644 --- a/third_party/khronos/README.chromium +++ b/third_party/khronos/README.chromium
@@ -31,6 +31,7 @@ EGL/eglplatform.h - Added EGLNative*Type for Mac. - Added EGLNative*Type for native linux framebuffers. + - Added EGLNative*Type for Fuchsia. EGL/eglext.h - Added support for EGL_EXT_image_flush_external extension - Added support for EGL_ANGLE_stream_producer_d3d_texture_nv12
diff --git a/third_party/libaddressinput/chromium/chrome_storage_impl.cc b/third_party/libaddressinput/chromium/chrome_storage_impl.cc index 2504eee..8228805b 100644 --- a/third_party/libaddressinput/chromium/chrome_storage_impl.cc +++ b/third_party/libaddressinput/chromium/chrome_storage_impl.cc
@@ -39,10 +39,8 @@ void ChromeStorageImpl::OnPrefValueChanged(const std::string& key) {} void ChromeStorageImpl::OnInitializationCompleted(bool succeeded) { - for (std::vector<Request*>::iterator iter = outstanding_requests_.begin(); - iter != outstanding_requests_.end(); ++iter) { - DoGet((*iter)->key, (*iter)->callback); - } + for (const auto& request : outstanding_requests_) + DoGet(request->key, request->callback); outstanding_requests_.clear(); } @@ -50,7 +48,7 @@ void ChromeStorageImpl::DoGet(const std::string& key, const Storage::Callback& data_ready) { if (!backing_store_->IsInitializationComplete()) { - outstanding_requests_.push_back(new Request(key, data_ready)); + outstanding_requests_.push_back(base::MakeUnique<Request>(key, data_ready)); return; }
diff --git a/third_party/libaddressinput/chromium/chrome_storage_impl.h b/third_party/libaddressinput/chromium/chrome_storage_impl.h index 6a08adc5..328784d 100644 --- a/third_party/libaddressinput/chromium/chrome_storage_impl.h +++ b/third_party/libaddressinput/chromium/chrome_storage_impl.h
@@ -6,10 +6,11 @@ #define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_CHROME_STORAGE_IMPL_H_ #include <list> +#include <memory> #include <string> +#include <vector> #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/scoped_observer.h" #include "components/prefs/pref_store.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" @@ -50,7 +51,7 @@ WriteablePrefStore* backing_store_; // weak // Get requests that haven't yet been serviced. - ScopedVector<Request> outstanding_requests_; + std::vector<std::unique_ptr<Request>> outstanding_requests_; ScopedObserver<PrefStore, ChromeStorageImpl> scoped_observer_;
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index 2f95c5f..dc7d5e3 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -261,6 +261,10 @@ 'lib/clang/*/lib/darwin/*asan_iossim*', 'lib/clang/*/lib/darwin/*profile_osx*', 'lib/clang/*/lib/darwin/*profile_iossim*', + # And the OSX and ios builtin libraries (iossim is lipo'd into + # ios) for the _IsOSVersionAtLeast runtime function. + 'lib/clang/*/lib/darwin/*.ios.a', + 'lib/clang/*/lib/darwin/*.osx.a', ]) elif sys.platform.startswith('linux'): # Copy the libstdc++.so.6 we linked Clang against so it can run.
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index e96e4b55..fb597db 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -34,7 +34,7 @@ CLANG_REVISION = 'HEAD' # This is incremented when pushing a new build of Clang at the same revision. -CLANG_SUB_REVISION=2 +CLANG_SUB_REVISION=3 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/tools/gn/misc/emacs/gn-mode.el b/tools/gn/misc/emacs/gn-mode.el index c2cd1bd..931207ba 100644 --- a/tools/gn/misc/emacs/gn-mode.el +++ b/tools/gn/misc/emacs/gn-mode.el
@@ -61,28 +61,38 @@ '("true" "false" "if" "else")) (defvar gn-font-lock-target-declaration-keywords - '("action" "action_foreach" "copy" "executable" "group" "loadable_module" - "shared_library" "source_set" "static_library")) + '("action" "action_foreach" "bundle_data" "copy" "create_bundle" "executable" + "group" "loadable_module" "shared_library" "source_set" "static_library" + "target")) +;; pool() is handled specially since it's also a variable name (defvar gn-font-lock-buildfile-fun-keywords '("assert" "config" "declare_args" "defined" "exec_script" "foreach" - "get_label_info" "get_path_info" "get_target_outputs" "getenv" "import" - "print" "process_file_template" "read_file" "rebase_path" - "set_default_toolchain" "set_defaults" "set_sources_assignment_filter" - "template" "tool" "toolchain" "toolchain_args" "write_file")) + "forward_variables_from" "get_label_info" "get_path_info" + "get_target_outputs" "getenv" "import" "not_needed" "print" + "process_file_template" "read_file" "rebase_path" "set_default_toolchain" + "set_defaults" "set_sources_assignment_filter" "split_list" "template" + "tool" "toolchain" "write_file")) (defvar gn-font-lock-predefined-var-keywords '("current_cpu" "current_os" "current_toolchain" "default_toolchain" - "host_cpu" "host_os" "python_path" "root_build_dir" "root_gen_dir" - "root_out_dir" "target_cpu" "target_gen_dir" "target_os" "target_out_dir")) + "host_cpu" "host_os" "invoker" "python_path" "root_build_dir" "root_gen_dir" + "root_out_dir" "target_cpu" "target_gen_dir" "target_name" "target_os" + "target_out_dir")) (defvar gn-font-lock-var-keywords - '("all_dependent_configs" "allow_circular_includes_from" "args" "asmflags" - "cflags" "cflags_c" "cflags_cc" "cflags_objc" "cflags_objcc" - "check_includes" "complete_static_lib" "configs" "data" "data_deps" + '("all_dependent_configs" "allow_circular_includes_from" "arflags" "args" + "asmflags" "assert_no_deps" "bundle_deps_filter" "bundle_executable_dir" + "bundle_plugins_dir" "bundle_resources_dir" "bundle_root_dir" "cflags" + "cflags_c" "cflags_cc" "cflags_objc" "cflags_objcc" "check_includes" + "code_signing_args" "code_signing_outputs" "code_signing_script" + "code_signing_sources" "complete_static_lib" "configs" "data" "data_deps" "defines" "depfile" "deps" "include_dirs" "inputs" "ldflags" "lib_dirs" - "libs" "output_extension" "output_name" "outputs" "public" "public_configs" - "public_deps" "script" "sources" "testonly" "visibility")) + "libs" "output_dir" "output_extension" "output_name" + "output_prefix_override" "outputs" "pool" "precompiled_header" + "precompiled_header_type" "precompiled_source" "product_type" "public" + "public_configs" "public_deps" "response_file_contents" "script" "sources" + "testonly" "visibility" "write_runtime_deps")) (defconst gn-font-lock-keywords `((,(regexp-opt gn-font-lock-reserved-keywords 'words) . @@ -91,6 +101,9 @@ font-lock-type-face) (,(regexp-opt gn-font-lock-buildfile-fun-keywords 'words) . font-lock-function-name-face) + ;; pool() as a function + ("\\<\\(pool\\)\\s-*(" + (1 font-lock-function-name-face)) (,(regexp-opt gn-font-lock-predefined-var-keywords 'words) . font-lock-constant-face) (,(regexp-opt gn-font-lock-var-keywords 'words) .
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc index c41e4f1..d029291 100644 --- a/tools/gn/xcode_writer.cc +++ b/tools/gn/xcode_writer.cc
@@ -38,6 +38,7 @@ const char kEarlGreyFileNameIdentifier[] = "egtest.mm"; const char kXCTestFileNameIdentifier[] = "xctest.mm"; const char kXCTestModuleTargetNamePostfix[] = "_module"; +const char kXCUITestRunnerTargetNamePostfix[] = "_runner"; struct SafeEnvironmentVariableInfo { const char* name; @@ -100,6 +101,13 @@ "com.apple.product-type.application"; } +bool IsXCUITestRunnerTarget(const Target* target) { + return IsApplicationTarget(target) && + base::EndsWith(target->label().name(), + kXCUITestRunnerTargetNamePostfix, + base::CompareCase::SENSITIVE); +} + bool IsXCTestModuleTarget(const Target* target) { return target->output_type() == Target::CREATE_BUNDLE && target->bundle_data().product_type() == @@ -108,6 +116,14 @@ base::CompareCase::SENSITIVE); } +bool IsXCUITestModuleTarget(const Target* target) { + return target->output_type() == Target::CREATE_BUNDLE && + target->bundle_data().product_type() == + "com.apple.product-type.bundle.ui-testing" && + base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix, + base::CompareCase::SENSITIVE); +} + bool IsXCTestFile(const SourceFile& file) { return base::EndsWith(file.GetName(), kEarlGreyFileNameIdentifier, base::CompareCase::SENSITIVE) || @@ -488,6 +504,18 @@ if (target->bundle_data().product_type().empty()) continue; + // For XCUITest, two CREATE_BUNDLE targets are generated: + // ${target_name}_runner and ${target_name}_module, however, Xcode + // requires only one target named ${target_name} to run tests. + if (IsXCUITestRunnerTarget(target)) + continue; + std::string pbxtarget_name = target->label().name(); + if (IsXCUITestModuleTarget(target)) { + std::string target_name = target->label().name(); + pbxtarget_name = target_name.substr( + 0, target_name.rfind(kXCTestModuleTargetNamePostfix)); + } + // Test files need to be known to Xcode for proper indexing and for // discovery of tests function for XCTest, but the compilation is done // via ninja and thus must prevent Xcode from linking object files via @@ -500,13 +528,13 @@ } PBXNativeTarget* native_target = main_project->AddNativeTarget( - target->label().name(), std::string(), + pbxtarget_name, std::string(), RebasePath(target->bundle_data() .GetBundleRootDirOutput(target->settings()) .value(), build_settings->build_dir()), target->bundle_data().product_type(), - GetBuildScript(target->label().name(), ninja_extra_args, env.get()), + GetBuildScript(pbxtarget_name, ninja_extra_args, env.get()), extra_attributes); bundle_target_to_pbxtarget.insert( std::make_pair(target, native_target));
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 14c92ac..7633e42 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -34,6 +34,10 @@ </action> <action name="AboutConflicts"> + <obsolete> + Deprecated since the conflicts page is changing. TODO(pmonette): Update this + to refer to the action for the new conflicts page. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action> @@ -17289,6 +17293,10 @@ </action> <action name="ViewAboutConflicts"> + <obsolete> + Deprecated since the conflicts page is changing. TODO(pmonette): Update this + to refer to the action for the new conflicts page. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d0fcbaf..b732eff 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -19052,7 +19052,7 @@ <int value="3" label="Create tables"/> <int value="4" label="Version check and migration (check - History.MigrateFailureToVersion)"/> + History.MigrateFailureFromVersion)"/> <int value="5" label="Commit"/> </enum> @@ -22453,6 +22453,8 @@ <int value="-1797739460" label="brotli-encoding:disabled"/> <int value="-1790227231" label="show-autofill-signatures"/> <int value="-1784788154" label="NewRemotePlaybackPipeline:disabled"/> + <int value="-1780306716" + label="OmniboxSpeculativeServiceWorkerStartOnQueryInput:enabled"/> <int value="-1772172557" label="enable-osk-overscroll"/> <int value="-1767470652" label="out-of-process-pdf"/> <int value="-1751928267" label="disable-icon-ntp"/> @@ -22676,6 +22678,8 @@ <int value="-1015006759" label="ImportantSitesInCBD:disabled"/> <int value="-998255750" label="ExperimentalKeyboardLockUI:enabled"/> <int value="-996673716" label="enable-web-app-frame"/> + <int value="-991253797" + label="OmniboxSpeculativeServiceWorkerStartOnQueryInput:disabled"/> <int value="-980260493" label="NTPSnippets:disabled"/> <int value="-979313250" label="enable-google-branded-context-menu"/> <int value="-979057409" label="enable-seccomp-filter-sandbox"/> @@ -37111,6 +37115,18 @@ <int value="10" label="Can not close extracted file"/> </enum> +<enum name="UnsupportedContainers"> + <int value="0" label="3GP"/> + <int value="1" label="TS"/> + <int value="2" label="MID"/> + <int value="3" label="XMF"/> + <int value="4" label="MXMF"/> + <int value="5" label="RTTTL"/> + <int value="6" label="RTX"/> + <int value="7" label="OTA"/> + <int value="8" label="IMY"/> +</enum> + <enum name="UpdateEngineAttemptResult"> <int value="0" label="Update Succeeded"/> <int value="1" label="Internal Error"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 6c1a5189..40eaa90 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -27796,6 +27796,21 @@ <summary>Records events related to local discovery notifications.</summary> </histogram> +<histogram name="LocalNetworkRequests.PrivatePage" units="requests"> + <owner>uthakore@chromium.org</owner> + <summary> + Number of requests made by a private page to resources besides itself. + </summary> +</histogram> + +<histogram name="LocalNetworkRequests.PublicPage" units="requests"> + <owner>uthakore@chromium.org</owner> + <summary> + Number of requests made by a public page to resources with reserved IP + addresses. + </summary> +</histogram> + <histogram name="LocalStorage.BrowserLocalStorageCachePurgedInKB" units="KB"> <owner>ssid@chromium.org</owner> <summary> @@ -31325,6 +31340,16 @@ </summary> </histogram> +<histogram name="Media.WebView.UnsupportedContainer" + enum="UnsupportedContainers"> + <owner>dalecurtis@chromium.org</owner> + <summary> + Media container extensions seen by WebView that are not supported by the + standard HTML5 playback path. This value is recorded every time a + WebMediaPlayer is created with one of the unsupported containers. + </summary> +</histogram> + <histogram name="Media.WindowsCoreAudioInput" enum="BooleanSuccess"> <obsolete> Deprecated 01/2017 as Windows Core Audio is now the only audio input @@ -53158,6 +53183,16 @@ </histogram> <histogram + name="PaymentRequest.UserDidNotHaveInitialFormOfPayment.EffectOnCompletion" + enum="PaymentRequestFlowCompletionStatus"> + <owner>sebsg@chromium.org</owner> + <summary> + Whether the flow was completed when the user did not have a form of payment + on file when the Payment Request was shown. + </summary> +</histogram> + +<histogram name="PaymentRequest.UserDidNotHaveSuggestionsForEverything.EffectOnCompletion" enum="PaymentRequestFlowCompletionStatus"> <owner>sebsg@chromium.org</owner> @@ -53167,6 +53202,15 @@ </summary> </histogram> +<histogram name="PaymentRequest.UserHadInitialFormOfPayment.EffectOnCompletion" + enum="PaymentRequestFlowCompletionStatus"> + <owner>sebsg@chromium.org</owner> + <summary> + Whether the flow was completed when the user had an a form of payment on + file when the Payment Request was shown. + </summary> +</histogram> + <histogram name="PaymentRequest.UserHadSuggestionsForEverything.EffectOnCompletion" enum="PaymentRequestFlowCompletionStatus"> @@ -91369,6 +91413,71 @@ <affected-histogram name="LevelDB.Open"/> </histogram_suffixes> +<histogram_suffixes name="LocalNetReqsLocalhostResources" separator="."> + <suffix name="Localhost.DbRequests" + label="Requests made to localhost on a database server port."/> + <suffix name="Localhost.DevRequests" + label="Requests made to localhost on a development server port."/> + <suffix name="Localhost.OtherRequests" + label="Requests made to localhost on any port not otherwise monitored + by the other local network request metrics."/> + <suffix name="Localhost.PrinterRequests" + label="Requests made to localhost on a printer server port."/> + <suffix name="Localhost.WebRequests" + label="Requests made to localhost on a web server port."/> + <affected-histogram name="LocalNetworkRequests.PrivatePage"/> + <affected-histogram name="LocalNetworkRequests.PublicPage"/> +</histogram_suffixes> + +<histogram_suffixes name="LocalNetReqsPrivatePage" separator="."> + <suffix name="DifferentSubnetRequests" + label="Requests made to local resources on a different subnet."/> + <suffix name="PublicRequests" label="Requests made to public resources."/> + <suffix name="SameSubnetRequests" + label="Requests made to local resources on the same reserved IP space + as the page."/> + <affected-histogram name="LocalNetworkRequests.PrivatePage"/> +</histogram_suffixes> + +<histogram_suffixes name="LocalNetReqsPublicPage" separator="."> + <suffix name="PrivateRequests" label="Requests made to private resources."/> + <suffix name="RouterRequests" + label="Requests made to resources likely to be routers."/> + <affected-histogram name="LocalNetworkRequests.PublicPage"/> +</histogram_suffixes> + +<histogram_suffixes name="LocalNetReqsStatuses" separator="."> + <suffix name="Failed" label="Failed requests."/> + <suffix name="Successful" label="Successful requests."/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.DifferentSubnetRequests"/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.Localhost.DbRequests"/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.Localhost.DevRequests"/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.Localhost.OtherRequests"/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.Localhost.PrinterRequests"/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.Localhost.WebRequests"/> + <affected-histogram name="LocalNetworkRequests.PrivatePage.PublicRequests"/> + <affected-histogram + name="LocalNetworkRequests.PrivatePage.SameSubnetRequests"/> + <affected-histogram + name="LocalNetworkRequests.PublicPage.Localhost.DbRequests"/> + <affected-histogram + name="LocalNetworkRequests.PublicPage.Localhost.DevRequests"/> + <affected-histogram + name="LocalNetworkRequests.PublicPage.Localhost.OtherRequests"/> + <affected-histogram + name="LocalNetworkRequests.PublicPage.Localhost.PrinterRequests"/> + <affected-histogram + name="LocalNetworkRequests.PublicPage.Localhost.WebRequests"/> + <affected-histogram name="LocalNetworkRequests.PublicPage.PrivateRequests"/> + <affected-histogram name="LocalNetworkRequests.PublicPage.RouterRequests"/> +</histogram_suffixes> + <histogram_suffixes name="LocalStorageCachePurgeReason" separator="."> <suffix name="AggressivePurgeTriggered" label="Aggressive purge was triggered on memory pressure."/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index a983545..d9cb199 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -395,6 +395,52 @@ </metric> </event> +<event name="LocalNetworkRequests"> + <owner>uthakore@chromium.org</owner> + <summary> + Metrics that describe the resource request behavior of pages for which + navigation successfully commits. A separate entry is generated for every + unique IP address or localhost port number to which the loaded page makes a + resource request. + </summary> + <metric name="Count.Failed"> + <summary> + The count of requests made by the page to the given resource for which a + response is not received or a network error occurs (i.e. |net_error| != + |net::OK|) between the time navigation to the page commits and the time it + completes. + </summary> + </metric> + <metric name="Count.Successful"> + <summary> + The count of requests made by the page to the given resource for which a + successful response is received (i.e. |net_error| == |net::OK|) between + the time navigation to the page commits and the time it completes. + </summary> + </metric> + <metric name="PortType"> + <summary> + An enum value representing the type of port for requests to localhost. The + enum is defined in |LocalNetworkRequestsPageLoadMetricsObserver|. Possible + values are 1 for common web server ports, 2 for common database server + ports, 4 for common print server ports, 8 for common development server + ports, and 0 for all other ports. + </summary> + </metric> + <metric name="ResourceType"> + <summary> + An enum value representing the type of resource requested. The enum is + defined in |LocalNetworkRequestsPageLoadMetricsObserver|. Possible values + are 0 for public resources requested by private pages, 1 for private + resources requested by public pages, 2 for private resources within the + same reserved IP space as the loaded private page, 4 for for private + resources within a different reserved IP space than the loaded private + page, 8 for resources requested by public pages that are suspected to be + routers, and 16 for localhost resources. + </summary> + </metric> +</event> + <event name="Media.WatchTime"> <owner>dalecurtis@chromium.org</owner> <summary> @@ -443,6 +489,24 @@ <metric name="AudioVideo.SRC"/> </event> +<event name="PageDomainInfo"> + <owner>uthakore@chromium.org</owner> + <summary> + Metrics that describe the domain of pages that successfully commit. One + event is generated per page load that commits. Currently associated with + LocalNetworkRequests UKM metric collection. + </summary> + <metric name="DomainType"> + <summary> + An enum value representing the type of domain of the loaded page. The enum + is defined in |LocalNetworkRequestsPageLoadMetricsObserver|. Possible + values are 0 for unknown (should never be logged), 1 for pages with public + domains, 2 for pages with private domains (IP addresses that are part of a + reserved IP space not including localhost), or 4 for localhost. + </summary> + </metric> +</event> + <event name="PageLoad" singular="True"> <owner>bmcquade@chromium.org</owner> <summary>
diff --git a/tools/perf/benchmarks/tab_switching.py b/tools/perf/benchmarks/tab_switching.py index 9eec5c8b..ad9b94ac 100644 --- a/tools/perf/benchmarks/tab_switching.py +++ b/tools/perf/benchmarks/tab_switching.py
@@ -15,8 +15,6 @@ @benchmark.Owner(emails=['vovoy@chromium.org'], component='OS>Performance') @benchmark.Enabled('has tabs') -@benchmark.Disabled('mac') # http://crbug.com/612774 -@benchmark.Disabled('android') # http://crbug.com/460084 class TabSwitchingTypical25(perf_benchmark.PerfBenchmark): """This test records the MPArch.RWH_TabSwitchPaintDuration histogram.
diff --git a/tools/perf/chromium.perf.fyi.extras.json b/tools/perf/chromium.perf.fyi.extras.json new file mode 100644 index 0000000..bbb1dbe --- /dev/null +++ b/tools/perf/chromium.perf.fyi.extras.json
@@ -0,0 +1,31 @@ +{ + "comment": [ + "This file contains manually-specified tests that should be merged into", + "testing/buildbot/chromium.perf.fyi.json." + ], + "Mojo Linux Perf": { + "isolated_scripts": [ + { + "args": [ + "loading.desktop.network_service", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=release" + ], + "isolate_name": "telemetry_perf_tests", + "name": "loading.desktop.network_service", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "expiration": 36000, + "hard_timeout": 10800, + "ignore_task_failure": false, + "io_timeout": 3600 + } + } + ] + } +}
diff --git a/tools/perf/contrib/network_service/__init__.py b/tools/perf/contrib/network_service/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/perf/contrib/network_service/__init__.py
diff --git a/tools/perf/contrib/network_service/loading.py b/tools/perf/contrib/network_service/loading.py new file mode 100644 index 0000000..c2d29917 --- /dev/null +++ b/tools/perf/contrib/network_service/loading.py
@@ -0,0 +1,30 @@ +# 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. + +from benchmarks import loading + +from telemetry import benchmark + + +@benchmark.Owner(emails=['yzshen@chromium.org']) +class LoadingDesktopNetworkService(loading.LoadingDesktop): + """Measures loading performance of desktop sites, with the network service + enabled. + """ + @classmethod + def Name(cls): + return 'loading.desktop.network_service' + + def SetExtraBrowserOptions(self, options): + enable_features_arg = '--enable-features=NetworkService' + + # If an "--enable-features" argument has been specified, append to the value + # list of that argument. + for arg in options.extra_browser_args: + if arg.startswith('--enable-features='): + options.extra_browser_args.remove(arg) + enable_features_arg = arg + ',NetworkService' + break + + options.AppendExtraBrowserArgs([ enable_features_arg, '--incognito' ])
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index a4119dee..a0e40c2 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -853,17 +853,42 @@ return os.path.join(buildbot_dir, filename) +def get_extras_json_config_file_for_waterfall(waterfall): + filename = '%s.extras.json' % waterfall['name'] + buildbot_dir = os.path.join(path_util.GetChromiumSrcDir(), 'tools', 'perf') + return os.path.join(buildbot_dir, filename) + + +def append_extra_tests(waterfall, tests): + """Appends extra tests to |tests|. + + Those extra tests are loaded from tools/perf/<waterfall name>.extras.json. + """ + extra_config_file = get_extras_json_config_file_for_waterfall(waterfall) + if os.path.isfile(extra_config_file): + with open(extra_config_file) as extra_fp: + extra_tests = json.load(extra_fp) + for key, value in extra_tests.iteritems(): + if key == 'comment': + continue + assert key not in tests + tests[key] = value + + def tests_are_up_to_date(waterfalls): up_to_date = True all_tests = {} for w in waterfalls: tests = generate_all_tests(w) + # Note: |all_tests| don't cover those manually-specified tests added by + # append_extra_tests(). + all_tests.update(tests) + append_extra_tests(w, tests) tests_data = json.dumps(tests, indent=2, separators=(',', ': '), sort_keys=True) config_file = get_json_config_file_for_waterfall(w) with open(config_file, 'r') as fp: config_data = fp.read().strip() - all_tests.update(tests) up_to_date &= tests_data == config_data verify_all_tests_in_benchmark_csv(all_tests, get_all_waterfall_benchmarks_metadata()) @@ -874,11 +899,14 @@ all_tests = {} for w in waterfalls: tests = generate_all_tests(w) + # Note: |all_tests| don't cover those manually-specified tests added by + # append_extra_tests(). + all_tests.update(tests) + append_extra_tests(w, tests) config_file = get_json_config_file_for_waterfall(w) with open(config_file, 'w') as fp: json.dump(tests, fp, indent=2, separators=(',', ': '), sort_keys=True) fp.write('\n') - all_tests.update(tests) verify_all_tests_in_benchmark_csv(all_tests, get_all_waterfall_benchmarks_metadata())
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py index 6240d16..786e3fe3 100644 --- a/tools/perf/core/perf_data_generator_unittest.py +++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -275,3 +275,30 @@ 'build1-b1': ['test'], 'build2-b1': ['other_test', 'test'], })) + + def testExtraTestsAreLoadedFromFile(self): + tests = { + 'Linux Perf': {} + } + + mock_extras_json = ''' + { + "comment": [ "This is comment and therefore should be skipped." ], + "Mojo Linux Perf": {} + } + ''' + + mock_waterfall_name = 'hello' + + def mockIsFile(path): + return path.endswith('%s.extras.json' % mock_waterfall_name) + + with mock.patch('os.path.isfile', side_effect=mockIsFile): + with mock.patch('__builtin__.open', + mock.mock_open(read_data=mock_extras_json)): + perf_data_generator.append_extra_tests({'name': mock_waterfall_name}, + tests) + + self.assertTrue('Linux Perf' in tests) + self.assertTrue('Mojo Linux Perf' in tests) + self.assertFalse('comment' in tests)
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py index f5d1a590..c9bd4c67 100644 --- a/tools/perf/page_sets/system_health/browsing_stories.py +++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -10,7 +10,6 @@ from page_sets.login_helpers import facebook_login from page_sets.login_helpers import pinterest_login -from telemetry.core import exceptions from telemetry.util import js_template @@ -788,7 +787,6 @@ SCROLL_DISTANCE = 25000 SCROLL_STEP = 1000 MAX_SCROLL_RETRIES = 3 - TIME_BEFORE_SCROLL_RETRY_IN_SECONDS = 1 TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS = 5 def __init__(self, story_set, take_memory_measurement): @@ -812,26 +810,25 @@ """ This function scrolls the webpage by the given scroll distance in multiple steps, where each step (except the last one) has the given size. - If scrolling gets stuck, the functions retries scrolling MAX_SCROLL_RETRIES - times waiting TIME_BEFORE_SCROLL_RETRY_IN_SECONDS seconds between retries. + If scrolling gets stuck, the function waits for the page's scroll height to + expand then retries scrolling. """ remaining = distance - action_runner.EvaluateJavaScript('window.scrollY') - retry_count = 0 # Scroll until the window.scrollY is within 1 pixel of the target distance. while remaining > 1: + last_scroll_height = action_runner.EvaluateJavaScript( + 'document.body.scrollHeight') action_runner.ScrollPage(distance=min(remaining, step_size) + 1) new_remaining = (distance - action_runner.EvaluateJavaScript('window.scrollY')) if remaining <= new_remaining: # Scrolling is stuck. This can happen if the page is loading - # resources. Give the page some time and retry scrolling. - if retry_count == self.MAX_SCROLL_RETRIES: - raise exceptions.StoryActionError( - 'Scrolling stuck at %d' % remaining) - retry_count += 1 - action_runner.Wait(self.TIME_BEFORE_SCROLL_RETRY_IN_SECONDS) + # resources. Wait for the page's scrollheight to expand and retry + # scrolling. + action_runner.WaitForJavaScriptCondition( + 'document.body.scrollHeight > {{ last_scroll_height }} ', + last_scroll_height=last_scroll_height) else: - retry_count = 0 remaining = new_remaining @classmethod
diff --git a/tools/perf/page_sets/system_health/expectations.py b/tools/perf/page_sets/system_health/expectations.py index 45e87cd6..93b3b4c 100644 --- a/tools/perf/page_sets/system_health/expectations.py +++ b/tools/perf/page_sets/system_health/expectations.py
@@ -28,8 +28,6 @@ [expectations.ALL_WIN], 'crbug.com/728152') self.DisableStory('browse:news:cnn', [expectations.ALL_MAC], 'crbug.com/728576') - self.DisableStory('browse:social:twitter_infinite_scroll', - [expectations.ALL], 'crbug.com/728464') self.DisableStory('browse:media:flickr_infinite_scroll', [expectations.ALL], 'crbug.com/728785')
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 7ddbe98..22a9c49 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -66,6 +66,7 @@ "//ui/base", "//ui/display", "//ui/events", + "//ui/events/devices", "//ui/gfx", "//ui/gfx/geometry", "//url", @@ -213,6 +214,7 @@ "java/src/org/chromium/ui/display/DisplaySwitches.java", "java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java", "java/src/org/chromium/ui/display/VirtualDisplayAndroid.java", + "java/src/org/chromium/ui/events/devices/InputDeviceObserver.java", "java/src/org/chromium/ui/gfx/BitmapHelper.java", "java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java", "java/src/org/chromium/ui/gl/SurfaceTextureListener.java",
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc index 396c4324a..1423adb2 100644 --- a/ui/android/delegated_frame_host_android.cc +++ b/ui/android/delegated_frame_host_android.cc
@@ -11,9 +11,9 @@ #include "cc/layers/surface_layer.h" #include "cc/output/compositor_frame.h" #include "cc/output/copy_output_result.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_id.h" -#include "cc/surfaces/surface_manager.h" #include "ui/android/view_android.h" #include "ui/android/window_android_compositor.h" #include "ui/display/display.h" @@ -51,18 +51,18 @@ DelegatedFrameHostAndroid::DelegatedFrameHostAndroid( ui::ViewAndroid* view, - cc::SurfaceManager* surface_manager, + cc::FrameSinkManager* frame_sink_manager, Client* client, const cc::FrameSinkId& frame_sink_id) : frame_sink_id_(frame_sink_id), view_(view), - surface_manager_(surface_manager), + frame_sink_manager_(frame_sink_manager), client_(client), begin_frame_source_(this) { DCHECK(view_); DCHECK(client_); - surface_manager_->RegisterFrameSinkId(frame_sink_id_); + frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_); CreateNewCompositorFrameSinkSupport(); } @@ -70,7 +70,7 @@ DestroyDelegatedContent(); DetachFromCompositor(); support_.reset(); - surface_manager_->InvalidateFrameSinkId(frame_sink_id_); + frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_); } void DelegatedFrameHostAndroid::SubmitCompositorFrame( @@ -90,8 +90,9 @@ support_->SubmitCompositorFrame(local_surface_id, std::move(frame)); DCHECK(result); - content_layer_ = CreateSurfaceLayer(surface_manager_, surface_info_, - !has_transparent_background_); + content_layer_ = + CreateSurfaceLayer(frame_sink_manager_->surface_manager(), + surface_info_, !has_transparent_background_); view_->GetLayer()->AddChild(content_layer_); } else { support_->SubmitCompositorFrame(local_surface_id, std::move(frame)); @@ -114,8 +115,9 @@ DCHECK(surface_info_.is_valid()); DCHECK(!result_callback.is_null()); - scoped_refptr<cc::Layer> readback_layer = CreateSurfaceLayer( - surface_manager_, surface_info_, !has_transparent_background_); + scoped_refptr<cc::Layer> readback_layer = + CreateSurfaceLayer(frame_sink_manager_->surface_manager(), surface_info_, + !has_transparent_background_); readback_layer->SetHideLayerAndSubtree(true); compositor->AttachLayerForReadback(readback_layer); std::unique_ptr<cc::CopyOutputRequest> copy_output_request = @@ -198,7 +200,7 @@ constexpr bool needs_sync_points = true; support_.reset(); support_ = cc::CompositorFrameSinkSupport::Create( - this, surface_manager_, frame_sink_id_, is_root, + this, frame_sink_manager_, frame_sink_id_, is_root, handles_frame_sink_id_invalidation, needs_sync_points); }
diff --git a/ui/android/delegated_frame_host_android.h b/ui/android/delegated_frame_host_android.h index e2dd6569..8ddc3e8 100644 --- a/ui/android/delegated_frame_host_android.h +++ b/ui/android/delegated_frame_host_android.h
@@ -17,7 +17,7 @@ namespace cc { class CompositorFrame; -class SurfaceManager; +class FrameSinkManager; class SurfaceLayer; enum class SurfaceDrawStatus; @@ -40,7 +40,7 @@ }; DelegatedFrameHostAndroid(ViewAndroid* view, - cc::SurfaceManager* surface_manager, + cc::FrameSinkManager* frame_sink_manager, Client* client, const cc::FrameSinkId& frame_sink_id); @@ -91,7 +91,7 @@ ViewAndroid* view_; - cc::SurfaceManager* surface_manager_; + cc::FrameSinkManager* const frame_sink_manager_; WindowAndroidCompositor* registered_parent_compositor_ = nullptr; Client* client_;
diff --git a/ui/android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java b/ui/android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java new file mode 100644 index 0000000..df2254f --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java
@@ -0,0 +1,81 @@ +// 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.ui.events.devices; + +import android.content.Context; +import android.hardware.input.InputManager; +import android.hardware.input.InputManager.InputDeviceListener; + +import org.chromium.base.ContextUtils; +import org.chromium.base.ThreadUtils; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * A singleton that helps detecting changes in input devices through the interface + * {@link InputDeviceObserver}. + */ +@JNINamespace("ui") +public class InputDeviceObserver implements InputDeviceListener { + private static final InputDeviceObserver INSTANCE = new InputDeviceObserver(); + + /** + * Notifies the InputDeviceObserver that an observer is attached and it + * should prepare itself for listening input changes. + */ + @CalledByNative + public static void addObserver() { + assert ThreadUtils.runningOnUiThread(); + INSTANCE.attachObserver(); + } + + /** + * Notifies the InputDeviceObserver that an observer has been removed. + */ + @CalledByNative + public static void removeObserver() { + assert ThreadUtils.runningOnUiThread(); + INSTANCE.detachObserver(); + } + + private InputManager mInputManager; + private InputDeviceListener mInputDeviceListener; + private int mObserversCounter; + + // Override InputDeviceListener methods + @Override + public void onInputDeviceChanged(int deviceId) { + nativeInputConfigurationChanged(); + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + nativeInputConfigurationChanged(); + } + + @Override + public void onInputDeviceAdded(int deviceId) { + nativeInputConfigurationChanged(); + } + + private void attachObserver() { + if (mObserversCounter++ == 0) { + Context context = ContextUtils.getApplicationContext(); + mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE); + // Register an input device listener. + mInputManager.registerInputDeviceListener(this, null); + } + } + + private void detachObserver() { + assert mObserversCounter > 0; + if (--mObserversCounter == 0) { + mInputManager.unregisterInputDeviceListener(this); + mInputManager = null; + } + } + + private native void nativeInputConfigurationChanged(); +} \ No newline at end of file
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc index a416ebd1..c8a5afc 100644 --- a/ui/aura/demo/demo_main.cc +++ b/ui/aura/demo/demo_main.cc
@@ -138,10 +138,10 @@ #endif // The ContextFactory must exist before any Compositors are created. - viz::HostFrameSinkManager frame_sink_manager; - cc::SurfaceManager surface_manager; + viz::HostFrameSinkManager host_frame_sink_manager; + cc::FrameSinkManager frame_sink_manager; auto context_factory = base::MakeUnique<ui::InProcessContextFactory>( - &frame_sink_manager, &surface_manager); + &host_frame_sink_manager, &frame_sink_manager); context_factory->set_use_test_surface(false); // Create the message-loop here before creating the root window.
diff --git a/ui/aura/local/layer_tree_frame_sink_local.cc b/ui/aura/local/layer_tree_frame_sink_local.cc index 174dd676..196a7c4 100644 --- a/ui/aura/local/layer_tree_frame_sink_local.cc +++ b/ui/aura/local/layer_tree_frame_sink_local.cc
@@ -17,10 +17,10 @@ LayerTreeFrameSinkLocal::LayerTreeFrameSinkLocal( const cc::FrameSinkId& frame_sink_id, - cc::SurfaceManager* surface_manager) + cc::FrameSinkManager* frame_sink_manager) : cc::LayerTreeFrameSink(nullptr, nullptr, nullptr, nullptr), frame_sink_id_(frame_sink_id), - surface_manager_(surface_manager) {} + frame_sink_manager_(frame_sink_manager) {} LayerTreeFrameSinkLocal::~LayerTreeFrameSinkLocal() {} @@ -32,7 +32,7 @@ thread_checker_ = base::MakeUnique<base::ThreadChecker>(); support_ = cc::CompositorFrameSinkSupport::Create( - this, surface_manager_, frame_sink_id_, false /* is_root */, + this, frame_sink_manager_, frame_sink_id_, false /* is_root */, true /* handles_frame_sink_id_invalidation */, true /* needs_sync_points */); begin_frame_source_ = base::MakeUnique<cc::ExternalBeginFrameSource>(this);
diff --git a/ui/aura/local/layer_tree_frame_sink_local.h b/ui/aura/local/layer_tree_frame_sink_local.h index 55d05fe..7f8beaa 100644 --- a/ui/aura/local/layer_tree_frame_sink_local.h +++ b/ui/aura/local/layer_tree_frame_sink_local.h
@@ -17,7 +17,7 @@ namespace cc { class CompositorFrameSinkSupport; -class SurfaceManager; +class FrameSinkManager; } // namespace cc namespace aura { @@ -31,7 +31,7 @@ public cc::ExternalBeginFrameSourceClient { public: LayerTreeFrameSinkLocal(const cc::FrameSinkId& frame_sink_id, - cc::SurfaceManager* surface_manager); + cc::FrameSinkManager* frame_sink_manager); ~LayerTreeFrameSinkLocal() override; using SurfaceChangedCallback = @@ -59,7 +59,7 @@ private: const cc::FrameSinkId frame_sink_id_; - cc::SurfaceManager* const surface_manager_; + cc::FrameSinkManager* const frame_sink_manager_; std::unique_ptr<cc::CompositorFrameSinkSupport> support_; gfx::Size surface_size_; float device_scale_factor_ = 0;
diff --git a/ui/aura/local/window_port_local.cc b/ui/aura/local/window_port_local.cc index 64540ba..c2b2ad2 100644 --- a/ui/aura/local/window_port_local.cc +++ b/ui/aura/local/window_port_local.cc
@@ -4,7 +4,7 @@ #include "ui/aura/local/window_port_local.h" -#include "cc/surfaces/surface_manager.h" +#include "cc/surfaces/frame_sink_manager.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" #include "ui/aura/local/layer_tree_frame_sink_local.h" @@ -103,7 +103,7 @@ aura::Env::GetInstance()->context_factory_private(); frame_sink_id_ = context_factory_private->AllocateFrameSinkId(); auto frame_sink = base::MakeUnique<LayerTreeFrameSinkLocal>( - frame_sink_id_, context_factory_private->GetSurfaceManager()); + frame_sink_id_, context_factory_private->GetFrameSinkManager()); frame_sink->SetSurfaceChangedCallback(base::Bind( &WindowPortLocal::OnSurfaceChanged, weak_factory_.GetWeakPtr())); if (window_->GetRootWindow()) @@ -133,7 +133,8 @@ scoped_refptr<cc::SurfaceReferenceFactory> reference_factory = aura::Env::GetInstance() ->context_factory_private() - ->GetSurfaceManager() + ->GetFrameSinkManager() + ->surface_manager() ->reference_factory(); window_->layer()->SetShowPrimarySurface(surface_info, reference_factory); window_->layer()->SetFallbackSurface(surface_info);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 4441ecb..f7b9f78 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -367,7 +367,6 @@ sources += [ "touch/touch_device_win.cc" ] } else if (is_android) { sources += [ "touch/touch_device_android.cc" ] - sources -= [ "touch/touch_device_util.cc" ] } else if (is_ios) { sources += [ "touch/touch_device_ios.cc" ] } else if (is_linux) {
diff --git a/ui/base/touch/touch_device_android.cc b/ui/base/touch/touch_device_android.cc index 2a65323..92febc1 100644 --- a/ui/base/touch/touch_device_android.cc +++ b/ui/base/touch/touch_device_android.cc
@@ -20,7 +20,7 @@ return Java_TouchDevice_maxTouchPoints(AttachCurrentThread()); } -std::pair<int, int> GetAvailablePointerAndHoverTypes() { +std::pair<int, int> AvailablePointerAndHoverTypes() { JNIEnv* env = AttachCurrentThread(); std::vector<int> pointer_and_hover_types; base::android::JavaIntArrayToIntVector( @@ -30,6 +30,14 @@ return std::make_pair(pointer_and_hover_types[0], pointer_and_hover_types[1]); } +int GetAvailableHoverTypes() { + return AvailablePointerAndHoverTypes().second; +} + +int GetAvailablePointerTypes() { + return AvailablePointerAndHoverTypes().first; +} + PointerType GetPrimaryPointerType(int available_pointer_types) { if (available_pointer_types & POINTER_TYPE_COARSE) return POINTER_TYPE_COARSE;
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 01c52ef..d851a9b 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -30,8 +30,8 @@ #include "cc/output/context_provider.h" #include "cc/output/latency_info_swap_promise.h" #include "cc/scheduler/begin_frame_source.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" -#include "cc/surfaces/surface_manager.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -66,7 +66,7 @@ weak_ptr_factory_(this), lock_timeout_weak_ptr_factory_(this) { if (context_factory_private) { - context_factory_private->GetSurfaceManager()->RegisterFrameSinkId( + context_factory_private->GetFrameSinkManager()->RegisterFrameSinkId( frame_sink_id_); } root_web_layer_ = cc::Layer::Create(); @@ -200,7 +200,7 @@ context_factory_->RemoveCompositor(this); if (context_factory_private_) { - auto* manager = context_factory_private_->GetSurfaceManager(); + auto* manager = context_factory_private_->GetFrameSinkManager(); for (auto& client : child_frame_sinks_) { DCHECK(client.is_valid()); manager->UnregisterFrameSinkHierarchy(frame_sink_id_, client); @@ -216,7 +216,7 @@ void Compositor::AddFrameSink(const cc::FrameSinkId& frame_sink_id) { if (!context_factory_private_) return; - context_factory_private_->GetSurfaceManager()->RegisterFrameSinkHierarchy( + context_factory_private_->GetFrameSinkManager()->RegisterFrameSinkHierarchy( frame_sink_id_, frame_sink_id); child_frame_sinks_.insert(frame_sink_id); } @@ -227,7 +227,7 @@ auto it = child_frame_sinks_.find(frame_sink_id); DCHECK(it != child_frame_sinks_.end()); DCHECK(it->is_valid()); - context_factory_private_->GetSurfaceManager()->UnregisterFrameSinkHierarchy( + context_factory_private_->GetFrameSinkManager()->UnregisterFrameSinkHierarchy( frame_sink_id_, *it); child_frame_sinks_.erase(it); }
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 3245d5e..292d734 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -41,13 +41,13 @@ class AnimationHost; class AnimationTimeline; class ContextProvider; +class FrameSinkManager; class Layer; class LayerTreeDebugState; class LayerTreeFrameSink; class LayerTreeHost; class LocalSurfaceId; class ResourceSettings; -class SurfaceManager; class TaskGraphRunner; } @@ -105,8 +105,10 @@ // Allocate a new client ID for the display compositor. virtual cc::FrameSinkId AllocateFrameSinkId() = 0; - // Gets the surface manager. - virtual cc::SurfaceManager* GetSurfaceManager() = 0; + // Gets the frame sink manager. + // TODO(staraz): Remove GetFrameSinkManager once FrameSinkManager is merged + // into FrameSinkManagerImpl. + virtual cc::FrameSinkManager* GetFrameSinkManager() = 0; // Gets the frame sink manager host instance. virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0;
diff --git a/ui/compositor/test/context_factories_for_test.cc b/ui/compositor/test/context_factories_for_test.cc index ff5f348..0d1130bc 100644 --- a/ui/compositor/test/context_factories_for_test.cc +++ b/ui/compositor/test/context_factories_for_test.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/sys_info.h" +#include "cc/surfaces/frame_sink_manager.h" #include "components/viz/host/host_frame_sink_manager.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" #include "ui/compositor/compositor.h" @@ -56,7 +57,8 @@ g_host_frame_sink_manager = new viz::HostFrameSinkManager; g_frame_sink_manager_impl = new viz::FrameSinkManagerImpl(false, nullptr); g_implicit_factory = new InProcessContextFactory( - g_host_frame_sink_manager, g_frame_sink_manager_impl->surface_manager()); + g_host_frame_sink_manager, + g_frame_sink_manager_impl->frame_sink_manager()); g_implicit_factory->SetUseFastRefreshRateForTests(); *context_factory = g_implicit_factory; *context_factory_private = g_implicit_factory;
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index fcb27bc..0693e7e 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -21,6 +21,7 @@ #include "cc/surfaces/direct_layer_tree_frame_sink.h" #include "cc/surfaces/display.h" #include "cc/surfaces/display_scheduler.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/test/pixel_test_output_surface.h" #include "components/viz/host/host_frame_sink_manager.h" @@ -135,13 +136,13 @@ }; InProcessContextFactory::InProcessContextFactory( - viz::HostFrameSinkManager* frame_sink_manager, - cc::SurfaceManager* surface_manager) + viz::HostFrameSinkManager* host_frame_sink_manager, + cc::FrameSinkManager* frame_sink_manager) : frame_sink_id_allocator_(kDefaultClientId), use_test_surface_(true), - frame_sink_manager_(frame_sink_manager), - surface_manager_(surface_manager) { - DCHECK(frame_sink_manager); + host_frame_sink_manager_(host_frame_sink_manager), + frame_sink_manager_(frame_sink_manager) { + DCHECK(host_frame_sink_manager); DCHECK_NE(gl::GetGLImplementation(), gl::kGLImplementationNone) << "If running tests, ensure that main() is calling " << "gl::GLSurfaceTestSupport::InitializeOneOff()"; @@ -244,15 +245,15 @@ std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>( compositor->task_runner().get())); - GetSurfaceManager()->RegisterBeginFrameSource(begin_frame_source.get(), - compositor->frame_sink_id()); + GetFrameSinkManager()->RegisterBeginFrameSource(begin_frame_source.get(), + compositor->frame_sink_id()); // Note that we are careful not to destroy a prior |data->begin_frame_source| // until we have reset |data->display|. data->begin_frame_source = std::move(begin_frame_source); auto* display = per_compositor_data_[compositor.get()]->display.get(); auto layer_tree_frame_sink = base::MakeUnique<cc::DirectLayerTreeFrameSink>( - compositor->frame_sink_id(), GetSurfaceManager(), display, + compositor->frame_sink_id(), GetFrameSinkManager(), display, context_provider, shared_worker_context_provider_, &gpu_memory_buffer_manager_, &shared_bitmap_manager_); compositor->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); @@ -290,7 +291,7 @@ if (it == per_compositor_data_.end()) return; PerCompositorData* data = it->second.get(); - GetSurfaceManager()->UnregisterBeginFrameSource( + GetFrameSinkManager()->UnregisterBeginFrameSource( data->begin_frame_source.get()); DCHECK(data); #if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) @@ -317,12 +318,8 @@ return frame_sink_id_allocator_.NextFrameSinkId(); } -cc::SurfaceManager* InProcessContextFactory::GetSurfaceManager() { - return surface_manager_; -} - viz::HostFrameSinkManager* InProcessContextFactory::GetHostFrameSinkManager() { - return frame_sink_manager_; + return host_frame_sink_manager_; } void InProcessContextFactory::SetDisplayVisible(ui::Compositor* compositor, @@ -352,6 +349,10 @@ observer_list_.RemoveObserver(observer); } +cc::FrameSinkManager* InProcessContextFactory::GetFrameSinkManager() { + return frame_sink_manager_; +} + InProcessContextFactory::PerCompositorData* InProcessContextFactory::CreatePerCompositorData(ui::Compositor* compositor) { DCHECK(!per_compositor_data_[compositor]);
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 151c86be..2bb2b20 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "cc/surfaces/display.h" #include "cc/surfaces/frame_sink_id_allocator.h" +#include "cc/surfaces/frame_sink_manager.h" #include "cc/test/test_gpu_memory_buffer_manager.h" #include "cc/test/test_image_factory.h" #include "cc/test/test_shared_bitmap_manager.h" @@ -19,8 +20,8 @@ #include "ui/compositor/compositor.h" namespace cc { +class FrameSinkManager; class ResourceSettings; -class SurfaceManager; } namespace viz { @@ -33,12 +34,12 @@ class InProcessContextFactory : public ContextFactory, public ContextFactoryPrivate { public: - // Both |host_frame_sink_manager| and |surface_manager| must outlive the + // Both |host_frame_sink_manager| and |frame_sink_manager| must outlive the // ContextFactory. - // TODO(crbug.com/657959): |surface_manager| should go away and we should use - // the LayerTreeFrameSink from the HostFrameSinkManager. + // TODO(crbug.com/657959): |frame_sink_manager| should go away and we should + // use the LayerTreeFrameSink from the HostFrameSinkManager. InProcessContextFactory(viz::HostFrameSinkManager* host_frame_sink_manager, - cc::SurfaceManager* surface_manager); + cc::FrameSinkManager* frame_sink_manager); ~InProcessContextFactory() override; // If true (the default) an OutputSurface is created that does not display @@ -68,7 +69,6 @@ gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override; cc::TaskGraphRunner* GetTaskGraphRunner() override; cc::FrameSinkId AllocateFrameSinkId() override; - cc::SurfaceManager* GetSurfaceManager() override; viz::HostFrameSinkManager* GetHostFrameSinkManager() override; void SetDisplayVisible(ui::Compositor* compositor, bool visible) override; void ResizeDisplay(ui::Compositor* compositor, @@ -86,6 +86,7 @@ const cc::ResourceSettings& GetResourceSettings() const override; void AddObserver(ContextFactoryObserver* observer) override; void RemoveObserver(ContextFactoryObserver* observer) override; + cc::FrameSinkManager* GetFrameSinkManager() override; private: struct PerCompositorData; @@ -101,8 +102,8 @@ cc::FrameSinkIdAllocator frame_sink_id_allocator_; bool use_test_surface_; double refresh_rate_ = 60.0; - viz::HostFrameSinkManager* frame_sink_manager_; - cc::SurfaceManager* surface_manager_; + viz::HostFrameSinkManager* const host_frame_sink_manager_; + cc::FrameSinkManager* const frame_sink_manager_; base::ObserverList<ContextFactoryObserver> observer_list_; cc::RendererSettings renderer_settings_;
diff --git a/ui/events/devices/BUILD.gn b/ui/events/devices/BUILD.gn index 9565cc7..ca8c4e8 100644 --- a/ui/events/devices/BUILD.gn +++ b/ui/events/devices/BUILD.gn
@@ -2,6 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + component("devices") { sources = [ "device_data_manager.cc", @@ -15,6 +20,8 @@ "input_device_event_observer.h", "input_device_manager.cc", "input_device_manager.h", + "input_device_observer_android.cc", + "input_device_observer_android.h", "input_device_observer_win.cc", "input_device_observer_win.h", "stylus_state.h", @@ -35,4 +42,17 @@ "//ui/display/types", "//ui/gfx/geometry", ] + + if (is_android) { + deps += [ ":ui_events_devices_jni_headers" ] + } +} + +if (is_android) { + generate_jni("ui_events_devices_jni_headers") { + sources = [ + "../../android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java", + ] + jni_package = "events/devices" + } }
diff --git a/ui/events/devices/DEPS b/ui/events/devices/DEPS new file mode 100644 index 0000000..1d2c11b --- /dev/null +++ b/ui/events/devices/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "input_device_observer_android.cc": [ + "+jni", + ], +}
diff --git a/ui/events/devices/input_device_observer_android.cc b/ui/events/devices/input_device_observer_android.cc new file mode 100644 index 0000000..3313b7fe --- /dev/null +++ b/ui/events/devices/input_device_observer_android.cc
@@ -0,0 +1,67 @@ +// 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 "ui/events/devices/input_device_observer_android.h" + +#include "base/memory/singleton.h" +#include "jni/InputDeviceObserver_jni.h" + +using base::android::AttachCurrentThread; +using base::android::JavaParamRef; + +// This macro provides the implementation for the observer notification methods. +#define NOTIFY_OBSERVERS(method_decl, observer_call) \ + void InputDeviceObserverAndroid::method_decl { \ + for (ui::InputDeviceEventObserver & observer : observers_) \ + observer.observer_call; \ + } + +namespace ui { + +bool InputDeviceObserverAndroid::RegisterInputDeviceObserver(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +InputDeviceObserverAndroid::InputDeviceObserverAndroid() {} + +InputDeviceObserverAndroid::~InputDeviceObserverAndroid() {} + +InputDeviceObserverAndroid* InputDeviceObserverAndroid::GetInstance() { + return base::Singleton< + InputDeviceObserverAndroid, + base::LeakySingletonTraits<InputDeviceObserverAndroid>>::get(); +} + +void InputDeviceObserverAndroid::AddObserver( + ui::InputDeviceEventObserver* observer) { + observers_.AddObserver(observer); + JNIEnv* env = AttachCurrentThread(); + Java_InputDeviceObserver_addObserver(env); +} + +void InputDeviceObserverAndroid::RemoveObserver( + ui::InputDeviceEventObserver* observer) { + observers_.RemoveObserver(observer); + JNIEnv* env = AttachCurrentThread(); + Java_InputDeviceObserver_removeObserver(env); +} + +static void InputConfigurationChanged(JNIEnv* env, + const JavaParamRef<jobject>& obj) { + InputDeviceObserverAndroid::GetInstance() + ->NotifyObserversTouchpadDeviceConfigurationChanged(); + InputDeviceObserverAndroid::GetInstance() + ->NotifyObserversKeyboardDeviceConfigurationChanged(); + InputDeviceObserverAndroid::GetInstance() + ->NotifyObserversMouseDeviceConfigurationChanged(); +} + +NOTIFY_OBSERVERS(NotifyObserversMouseDeviceConfigurationChanged(), + OnMouseDeviceConfigurationChanged()); +NOTIFY_OBSERVERS(NotifyObserversTouchpadDeviceConfigurationChanged(), + OnTouchpadDeviceConfigurationChanged()); +NOTIFY_OBSERVERS(NotifyObserversKeyboardDeviceConfigurationChanged(), + OnKeyboardDeviceConfigurationChanged()); + +} // namespace ui \ No newline at end of file
diff --git a/ui/events/devices/input_device_observer_android.h b/ui/events/devices/input_device_observer_android.h new file mode 100644 index 0000000..311dfa82 --- /dev/null +++ b/ui/events/devices/input_device_observer_android.h
@@ -0,0 +1,48 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_ANDROID_H_ +#define UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_ANDROID_H_ + +#include <jni.h> + +#include "base/observer_list.h" +#include "ui/events/devices/input_device_event_observer.h" + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} + +namespace ui { + +// This class is a singleton responsible to notify the +// InputDeviceChangeObserver whenever an input change +// happened on the Java side. +class EVENTS_DEVICES_EXPORT InputDeviceObserverAndroid { + public: + static InputDeviceObserverAndroid* GetInstance(); + ~InputDeviceObserverAndroid(); + + static bool RegisterInputDeviceObserver(JNIEnv* env); + + void AddObserver(ui::InputDeviceEventObserver* observer); + void RemoveObserver(ui::InputDeviceEventObserver* observer); + + void NotifyObserversTouchpadDeviceConfigurationChanged(); + void NotifyObserversKeyboardDeviceConfigurationChanged(); + void NotifyObserversMouseDeviceConfigurationChanged(); + + private: + InputDeviceObserverAndroid(); + + base::ObserverList<ui::InputDeviceEventObserver> observers_; + + friend struct base::DefaultSingletonTraits<InputDeviceObserverAndroid>; + DISALLOW_COPY_AND_ASSIGN(InputDeviceObserverAndroid); +}; + +} // namespace ui + +#endif // UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_ANDROID_H_
diff --git a/ui/events/devices/input_device_observer_win.h b/ui/events/devices/input_device_observer_win.h index fd0f5b4..3390507 100644 --- a/ui/events/devices/input_device_observer_win.h +++ b/ui/events/devices/input_device_observer_win.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DEVICE_OBSERVER_WIN_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DEVICE_OBSERVER_WIN_H_ +#ifndef UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_WIN_H_ +#define UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_WIN_H_ #include "base/observer_list.h" #include "base/win/registry.h" @@ -45,4 +45,4 @@ } // namespace ui -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DEVICE_OBSERVER_WIN_H_ \ No newline at end of file +#endif // UI_EVENTS_DEVICES_INPUT_DEVICE_OBSERVER_WIN_H_ \ No newline at end of file
diff --git a/ui/events/keycodes/dom/dom_key_data.inc b/ui/events/keycodes/dom/dom_key_data.inc index c598dcdd..4362d55c 100644 --- a/ui/events/keycodes/dom/dom_key_data.inc +++ b/ui/events/keycodes/dom/dom_key_data.inc
@@ -361,6 +361,10 @@ DOM_KEY_MAP("LaunchWebBrowser", LAUNCH_WEB_BROWSER, 0x0B09), DOM_KEY_MAP("LaunchWebCam", LAUNCH_WEB_CAM, 0x0B0A), DOM_KEY_MAP("LaunchWordProcessor", LAUNCH_WORD_PROCESSOR, 0x0B0B), + // Note: Launch Assistant entry is currently Chrome-specific. + // It is not included in any web standard because it is not exposed + // to the web platform. + DOM_KEY_MAP("LaunchAssistant", LAUNCH_ASSISTANT, 0x0B0E), // ========================================================= // Browser Keys
diff --git a/ui/events/keycodes/dom/keycode_converter_data.inc b/ui/events/keycodes/dom/keycode_converter_data.inc index a62d390c..6c64672 100644 --- a/ui/events/keycodes/dom/keycode_converter_data.inc +++ b/ui/events/keycodes/dom/keycode_converter_data.inc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file has no header guard because it is explicily intended +// This file has no header guard because it is explicitly intended // to be included more than once with different definitions of the // macros USB_KEYMAP and USB_KEYMAP_DECLARATION. @@ -97,6 +97,9 @@ USB_KEYMAP(0x000014, 0x0000, 0x0000, 0x0000, 0xffff, "Suspend", SUSPEND), USB_KEYMAP(0x000015, 0x0000, 0x0000, 0x0000, 0xffff, "Resume", RESUME), USB_KEYMAP(0x000016, 0x0000, 0x0000, 0x0000, 0xffff, "Turbo", TURBO), + // AL Context-aware desktop assistant, not in HID specification (yet?) + USB_KEYMAP(0x000017, 0x0247, 0x024f, 0x0000, 0xffff, "LaunchAssistant", + LAUNCH_ASSISTANT), // ========================================= // USB Usage Page 0x01: Generic Desktop Page
diff --git a/ui/events/keycodes/dom/keycode_converter_unittest.cc b/ui/events/keycodes/dom/keycode_converter_unittest.cc index b6bab47..2fa7249 100644 --- a/ui/events/keycodes/dom/keycode_converter_unittest.cc +++ b/ui/events/keycodes/dom/keycode_converter_unittest.cc
@@ -23,8 +23,8 @@ // These are in the same order as the columns in keycode_converter_data.inc // as reflected in the USB_KEYMAP() macro below. const size_t expected_mapped_key_count[] = { - 207, // evdev - 207, // xkb + 208, // evdev + 208, // xkb 157, // windows 118, // mac };
diff --git a/ui/events/keycodes/dom_us_layout_data.h b/ui/events/keycodes/dom_us_layout_data.h index 4cf29e9..f6d295a 100644 --- a/ui/events/keycodes/dom_us_layout_data.h +++ b/ui/events/keycodes/dom_us_layout_data.h
@@ -177,6 +177,7 @@ {DomCode::LANG5, DomKey::ZENKAKU_HANKAKU}, {DomCode::LAUNCH_APP1, DomKey::LAUNCH_MY_COMPUTER}, {DomCode::LAUNCH_APP2, DomKey::LAUNCH_CALCULATOR}, + {DomCode::LAUNCH_ASSISTANT, DomKey::LAUNCH_ASSISTANT}, {DomCode::LAUNCH_AUDIO_BROWSER, DomKey::LAUNCH_MUSIC_PLAYER}, {DomCode::LAUNCH_CALENDAR, DomKey::LAUNCH_CALENDAR}, {DomCode::LAUNCH_CONTACTS, DomKey::LAUNCH_CONTACTS}, @@ -308,6 +309,7 @@ // Device Keys // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-device #if defined(OS_POSIX) + {DomKey::LAUNCH_ASSISTANT, VKEY_ASSISTANT}, {DomKey::BRIGHTNESS_DOWN, VKEY_BRIGHTNESS_DOWN}, {DomKey::BRIGHTNESS_UP, VKEY_BRIGHTNESS_UP}, {DomKey::POWER, VKEY_POWER}, @@ -413,6 +415,10 @@ // DomCode::SUSPEND 0x000014 Suspend // DomCode::RESUME 0x000015 Resume // DomCode::TURBO 0x000016 Turbo +#if defined(OS_POSIX) + {DomCode::LAUNCH_ASSISTANT, + VKEY_ASSISTANT}, // 0x000017 Launch Assistant +#endif {DomCode::SLEEP, VKEY_SLEEP}, // 0x010082 Sleep // DomCode::WAKE_UP 0x010083 WakeUp {DomCode::US_A, VKEY_A}, // 0x070004 KeyA
diff --git a/ui/events/keycodes/keyboard_code_conversion.cc b/ui/events/keycodes/keyboard_code_conversion.cc index aad6acf..c112545 100644 --- a/ui/events/keycodes/keyboard_code_conversion.cc +++ b/ui/events/keycodes/keyboard_code_conversion.cc
@@ -33,6 +33,19 @@ return 0; } +bool DomCodeToNonPrintableDomKey(DomCode dom_code, + DomKey* out_dom_key, + KeyboardCode* out_key_code) { + for (const auto& it : kNonPrintableCodeMap) { + if (it.dom_code == dom_code) { + *out_dom_key = it.dom_key; + *out_key_code = NonPrintableDomKeyToKeyboardCode(it.dom_key); + return true; + } + } + return false; +} + bool DomCodeToUsLayoutDomKey(DomCode dom_code, int flags, DomKey* out_dom_key, @@ -51,14 +64,8 @@ return true; } } - for (const auto& it : kNonPrintableCodeMap) { - if (it.dom_code == dom_code) { - *out_dom_key = it.dom_key; - *out_key_code = NonPrintableDomKeyToKeyboardCode(it.dom_key); - return true; - } - } - return false; + + return DomCodeToNonPrintableDomKey(dom_code, out_dom_key, out_key_code); } bool DomCodeToControlCharacter(DomCode dom_code,
diff --git a/ui/events/keycodes/keyboard_code_conversion.h b/ui/events/keycodes/keyboard_code_conversion.h index 10a26150..2815c8df 100644 --- a/ui/events/keycodes/keyboard_code_conversion.h +++ b/ui/events/keycodes/keyboard_code_conversion.h
@@ -48,6 +48,16 @@ KeyboardCode* key_code) WARN_UNUSED_RESULT; +// Helper function to map a physical key (dom_code) to a meaning (dom_key +// and character, together corresponding to the DOM keyboard event |key| +// value), along with a corresponding non-located Windows-based key_code. +// Unlike |DomCodeToUsLayoutDomKey| this function only maps non-printable, +// or action, keys. +EVENTS_BASE_EXPORT bool DomCodeToNonPrintableDomKey(DomCode dom_code, + DomKey* dom_key, + KeyboardCode* key_code) + WARN_UNUSED_RESULT; + // Obtains the control character corresponding to a physical key; // that is, the meaning of the physical key state (dom_code, and flags // containing EF_CONTROL_DOWN) under the base US English layout.
diff --git a/ui/events/keycodes/keyboard_codes_posix.h b/ui/events/keycodes/keyboard_codes_posix.h index 9c67648..31fe7195 100644 --- a/ui/events/keycodes/keyboard_codes_posix.h +++ b/ui/events/keycodes/keyboard_codes_posix.h
@@ -217,6 +217,7 @@ // and 0xE8 are unassigned. VKEY_WLAN = 0x97, VKEY_POWER = 0x98, + VKEY_ASSISTANT = 0x99, VKEY_BRIGHTNESS_DOWN = 0xD8, VKEY_BRIGHTNESS_UP = 0xD9, VKEY_KBD_BRIGHTNESS_DOWN = 0xDA,
diff --git a/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc b/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc index 474f2e9..f2f17545 100644 --- a/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc +++ b/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc
@@ -191,6 +191,8 @@ 'A'}, {DomCode::US_A, EF_CONTROL_DOWN, DomKey::Constant<'a'>::Character, VKEY_A, 1}, + {DomCode::LAUNCH_ASSISTANT, EF_NONE, DomKey::LAUNCH_ASSISTANT, + VKEY_ASSISTANT, 0}, }; KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc index fbe0fc6..6885d14 100644 --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
@@ -740,8 +740,12 @@ // Obtain keysym and character. xkb_keysym_t xkb_keysym; uint32_t character = 0; - if (!XkbLookup(xkb_keycode, xkb_flags, &xkb_keysym, &character)) - return false; + if (!XkbLookup(xkb_keycode, xkb_flags, &xkb_keysym, &character)) { + // If we do not have matching legacy Xkb keycode for the Dom code, + // we could be dealing with a newer application launcher or similar + // key. Let's see if we have a basic mapping for it. + return DomCodeToNonPrintableDomKey(dom_code, dom_key, key_code); + } // Classify the keysym and convert to DOM and VKEY representations. if (xkb_keysym != XKB_KEY_at || (flags & EF_CONTROL_DOWN) == 0) {
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc index b7e4cb3..02a8fd9 100644 --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
@@ -819,6 +819,9 @@ {{DomCode::ENTER, EF_NONE, XKB_KEY_Return}, VKEY_RETURN}, {{DomCode::NUMPAD_ENTER, EF_NONE, XKB_KEY_KP_Enter}, VKEY_RETURN}, {{DomCode::SLEEP, EF_NONE, XKB_KEY_XF86Sleep}, VKEY_SLEEP}, + // Verify that we can translate some Dom codes even if they are not + // known to XKB. + {{DomCode::LAUNCH_ASSISTANT, EF_NONE}, VKEY_ASSISTANT}, // Verify that number pad digits produce located VKEY codes. {{DomCode::NUMPAD0, EF_NONE, XKB_KEY_KP_0, '0'}, VKEY_NUMPAD0}, {{DomCode::NUMPAD9, EF_NONE, XKB_KEY_KP_9, '9'}, VKEY_NUMPAD9},
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index b333021..f4c414d 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -15,7 +15,7 @@ (target_cpu == "x86" || target_cpu == "x64") } -use_egl = is_win || is_android || is_linux +use_egl = is_win || is_android || is_linux || is_fuchsia use_glx = use_x11 || ozone_platform_x11 if (is_android) {
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py index 30b08d8..ab9ccede 100755 --- a/ui/gl/generate_bindings.py +++ b/ui/gl/generate_bindings.py
@@ -3001,6 +3001,9 @@ file.write('\n') file.write('} // namespace gl\n') +def SamePrefix(a, b): + return a[:a.rfind("_")] == b[:b.rfind("_")] + def GenerateEnumUtils(out_file, input_filenames): enum_re = re.compile(r'\#define\s+(GL_[a-zA-Z0-9_]+)\s+([0-9A-Fa-fx]+)') dict = {} @@ -3015,9 +3018,11 @@ if not value in dict: dict[value] = name # check our own _CHROMIUM macro conflicts with khronos GL headers. - elif dict[value] != name and (name.endswith('_CHROMIUM') or - dict[value].endswith('_CHROMIUM')): - raise RunTimeError("code collision: %s and %s have the same code %s" + # we allow for name duplication if they have the same prefix. + elif dict[value] != name and ((name.endswith('_CHROMIUM') or + dict[value].endswith('_CHROMIUM')) and + not SamePrefix(name, dict[value])): + raise RuntimeError("code collision: %s and %s have the same code %s" % (dict[value], name, value)) out_file.write(LICENSE_AND_HEADER)
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc index 79cc51c..e6d452ca 100644 --- a/ui/gl/gl_bindings_autogen_egl.cc +++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -164,8 +164,6 @@ ext.b_EGL_KHR_image = extensions.find("EGL_KHR_image ") != std::string::npos; ext.b_EGL_KHR_image_base = extensions.find("EGL_KHR_image_base ") != std::string::npos; - ext.b_EGL_KHR_reusable_sync = - extensions.find("EGL_KHR_reusable_sync ") != std::string::npos; ext.b_EGL_KHR_stream = extensions.find("EGL_KHR_stream ") != std::string::npos; ext.b_EGL_KHR_stream_consumer_gltexture =
diff --git a/ui/gl/gl_bindings_autogen_egl.h b/ui/gl/gl_bindings_autogen_egl.h index 4eb2e9dd..b8099205 100644 --- a/ui/gl/gl_bindings_autogen_egl.h +++ b/ui/gl/gl_bindings_autogen_egl.h
@@ -219,7 +219,6 @@ bool b_EGL_KHR_gl_texture_2D_image; bool b_EGL_KHR_image; bool b_EGL_KHR_image_base; - bool b_EGL_KHR_reusable_sync; bool b_EGL_KHR_stream; bool b_EGL_KHR_stream_consumer_gltexture; bool b_EGL_KHR_swap_buffers_with_damage;
diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h index bbbbed9..a746908 100644 --- a/ui/gl/gl_enums_implementation_autogen.h +++ b/ui/gl/gl_enums_implementation_autogen.h
@@ -13,7 +13,7 @@ 0, "GL_FALSE", }, { - 0x00, "GL_CLOSE_PATH_CHROMIUM", + 0x00, "GL_CLOSE_PATH_NV", }, { 0x0000, "GL_POINTS", @@ -28,13 +28,13 @@ 0x00000002, "GL_CONTEXT_FLAG_DEBUG_BIT_KHR", }, { - 0x00000004, "GL_GEOMETRY_SHADER_BIT_EXT", + 0x00000004, "GL_GEOMETRY_SHADER_BIT_OES", }, { - 0x00000008, "GL_TESS_CONTROL_SHADER_BIT_EXT", + 0x00000008, "GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR", }, { - 0x00000010, "GL_TESS_EVALUATION_SHADER_BIT_EXT", + 0x00000010, "GL_TESS_EVALUATION_SHADER_BIT_OES", }, { 0x00000020, "GL_COLOR_BUFFER_BIT5_QCOM", @@ -73,13 +73,13 @@ 0x0001, "GL_LINES", }, { - 0x00010000, "GL_STENCIL_BUFFER_BIT0_QCOM", + 0x00010000, "GL_FONT_X_MIN_BOUNDS_BIT_NV", }, { 0x0002, "GL_LINE_LOOP", }, { - 0x00020000, "GL_STENCIL_BUFFER_BIT1_QCOM", + 0x00020000, "GL_FONT_Y_MIN_BOUNDS_BIT_NV", }, { 0x0003, "GL_LINE_STRIP", @@ -88,7 +88,7 @@ 0x0004, "GL_TRIANGLES", }, { - 0x00040000, "GL_STENCIL_BUFFER_BIT2_QCOM", + 0x00040000, "GL_FONT_X_MAX_BOUNDS_BIT_NV", }, { 0x0005, "GL_TRIANGLE_STRIP", @@ -97,58 +97,70 @@ 0x0006, "GL_TRIANGLE_FAN", }, { - 0x0007, "GL_QUADS_EXT", + 0x0007, "GL_QUADS_OES", }, { 0x0008, "GL_MAP_INVALIDATE_BUFFER_BIT_EXT", }, { - 0x00080000, "GL_STENCIL_BUFFER_BIT3_QCOM", + 0x00080000, "GL_FONT_Y_MAX_BOUNDS_BIT_NV", }, { - 0x000A, "GL_LINES_ADJACENCY_EXT", + 0x000A, "GL_LINES_ADJACENCY_OES", }, { - 0x000B, "GL_LINE_STRIP_ADJACENCY_EXT", + 0x000B, "GL_LINE_STRIP_ADJACENCY_OES", }, { - 0x000C, "GL_TRIANGLES_ADJACENCY_EXT", + 0x000C, "GL_TRIANGLES_ADJACENCY_OES", }, { - 0x000D, "GL_TRIANGLE_STRIP_ADJACENCY_EXT", + 0x000D, "GL_TRIANGLE_STRIP_ADJACENCY_OES", }, { - 0x000E, "GL_PATCHES_EXT", + 0x000E, "GL_PATCHES_OES", }, { 0x0010, "GL_MAP_FLUSH_EXPLICIT_BIT_EXT", }, { - 0x00100000, "GL_STENCIL_BUFFER_BIT4_QCOM", + 0x00100000, "GL_FONT_UNITS_PER_EM_BIT_NV", }, { 0x0020, "GL_MAP_UNSYNCHRONIZED_BIT_EXT", }, { - 0x00200000, "GL_STENCIL_BUFFER_BIT5_QCOM", + 0x00200000, "GL_FONT_ASCENDER_BIT_NV", }, { - 0x00400000, "GL_STENCIL_BUFFER_BIT6_QCOM", + 0x0040, "GL_MAP_PERSISTENT_BIT_EXT", }, { - 0x00800000, "GL_STENCIL_BUFFER_BIT7_QCOM", + 0x00400000, "GL_FONT_DESCENDER_BIT_NV", }, { - 0x01000000, "GL_MULTISAMPLE_BUFFER_BIT0_QCOM", + 0x0080, "GL_MAP_COHERENT_BIT_EXT", }, { - 0x02, "GL_MOVE_TO_CHROMIUM", + 0x00800000, "GL_FONT_HEIGHT_BIT_NV", + }, + { + 0x01, "GL_BOLD_BIT_NV", + }, + { + 0x0100, "GL_DYNAMIC_STORAGE_BIT_EXT", + }, + { + 0x01000000, "GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV", + }, + { + 0x02, "GL_MOVE_TO_NV", }, { 0x0200, "GL_NEVER", }, { - 0x02000000, "GL_MULTISAMPLE_BUFFER_BIT1_QCOM", + 0x02000000, "GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV", }, { 0x0201, "GL_LESS", @@ -172,6 +184,9 @@ 0x0207, "GL_ALWAYS", }, { + 0x03, "GL_RELATIVE_MOVE_TO_NV", + }, + { 0x0300, "GL_SRC_COLOR", }, { @@ -199,10 +214,10 @@ 0x0308, "GL_SRC_ALPHA_SATURATE", }, { - 0x04, "GL_LINE_TO_CHROMIUM", + 0x04, "GL_LINE_TO_NV", }, { - 0x04000000, "GL_MULTISAMPLE_BUFFER_BIT2_QCOM", + 0x04000000, "GL_FONT_UNDERLINE_POSITION_BIT_NV", }, { 0x0404, "GL_FRONT", @@ -214,6 +229,9 @@ 0x0408, "GL_FRONT_AND_BACK", }, { + 0x05, "GL_RELATIVE_LINE_TO_NV", + }, + { 0x0500, "GL_INVALID_ENUM", }, { @@ -238,7 +256,19 @@ 0x0507, "GL_CONTEXT_LOST_KHR", }, { - 0x08000000, "GL_MULTISAMPLE_BUFFER_BIT3_QCOM", + 0x06, "GL_HORIZONTAL_LINE_TO_NV", + }, + { + 0x07, "GL_RELATIVE_HORIZONTAL_LINE_TO_NV", + }, + { + 0x08, "GL_VERTICAL_LINE_TO_NV", + }, + { + 0x08000000, "GL_FONT_UNDERLINE_THICKNESS_BIT_NV", + }, + { + 0x09, "GL_RELATIVE_VERTICAL_LINE_TO_NV", }, { 0x0900, "GL_CW", @@ -247,12 +277,18 @@ 0x0901, "GL_CCW", }, { - 0x0A, "GL_QUADRATIC_CURVE_TO_CHROMIUM", + 0x0A, "GL_QUADRATIC_CURVE_TO_NV", + }, + { + 0x0B, "GL_RELATIVE_QUADRATIC_CURVE_TO_NV", }, { 0x0B21, "GL_LINE_WIDTH", }, { + 0x0B40, "GL_POLYGON_MODE_NV", + }, + { 0x0B44, "GL_CULL_FACE", }, { @@ -307,10 +343,16 @@ 0x0BA2, "GL_VIEWPORT", }, { - 0x0BA6, "GL_PATH_MODELVIEW_MATRIX_CHROMIUM", + 0x0BA3, "GL_PATH_MODELVIEW_STACK_DEPTH_NV", }, { - 0x0BA7, "GL_PATH_PROJECTION_MATRIX_CHROMIUM", + 0x0BA4, "GL_PATH_PROJECTION_STACK_DEPTH_NV", + }, + { + 0x0BA6, "GL_PATH_MODELVIEW_MATRIX_NV", + }, + { + 0x0BA7, "GL_PATH_PROJECTION_MATRIX_NV", }, { 0x0BC0, "GL_ALPHA_TEST_QCOM", @@ -328,7 +370,7 @@ 0x0BE2, "GL_BLEND", }, { - 0x0C, "GL_CUBIC_CURVE_TO_CHROMIUM", + 0x0C, "GL_CUBIC_CURVE_TO_NV", }, { 0x0C01, "GL_DRAW_BUFFER_EXT", @@ -361,6 +403,9 @@ 0x0CF5, "GL_UNPACK_ALIGNMENT", }, { + 0x0D, "GL_RELATIVE_CUBIC_CURVE_TO_NV", + }, + { 0x0D02, "GL_PACK_ROW_LENGTH", }, { @@ -379,6 +424,12 @@ 0x0D33, "GL_MAX_TEXTURE_SIZE", }, { + 0x0D36, "GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV", + }, + { + 0x0D38, "GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV", + }, + { 0x0D3A, "GL_MAX_VIEWPORT_DIMS", }, { @@ -406,13 +457,28 @@ 0x0DE1, "GL_TEXTURE_2D", }, { + 0x0E, "GL_SMOOTH_QUADRATIC_CURVE_TO_NV", + }, + { + 0x0F, "GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV", + }, + { 0x1, "GL_CA_LAYER_EDGE_LEFT_CHROMIUM", }, { - 0x10000000, "GL_MULTISAMPLE_BUFFER_BIT4_QCOM", + 0x10, "GL_SMOOTH_CUBIC_CURVE_TO_NV", }, { - 0x1004, "GL_TEXTURE_BORDER_COLOR_EXT", + 0x100, "GL_GLYPH_HAS_KERNING_BIT_NV", + }, + { + 0x10000000, "GL_FONT_HAS_KERNING_BIT_NV", + }, + { + 0x1004, "GL_TEXTURE_BORDER_COLOR_OES", + }, + { + 0x11, "GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV", }, { 0x1100, "GL_DONT_CARE", @@ -424,6 +490,15 @@ 0x1102, "GL_NICEST", }, { + 0x12, "GL_SMALL_CCW_ARC_TO_NV", + }, + { + 0x13, "GL_RELATIVE_SMALL_CCW_ARC_TO_NV", + }, + { + 0x14, "GL_SMALL_CW_ARC_TO_NV", + }, + { 0x1400, "GL_BYTE", }, { @@ -451,21 +526,39 @@ 0x140C, "GL_FIXED", }, { + 0x140E, "GL_INT64_NV", + }, + { + 0x140F, "GL_UNSIGNED_INT64_NV", + }, + { + 0x15, "GL_RELATIVE_SMALL_CW_ARC_TO_NV", + }, + { 0x1506, "GL_XOR_NV", }, { 0x150A, "GL_INVERT", }, { - 0x1700, "GL_PATH_MODELVIEW_CHROMIUM", + 0x16, "GL_LARGE_CCW_ARC_TO_NV", }, { - 0x1701, "GL_PATH_PROJECTION_CHROMIUM", + 0x17, "GL_RELATIVE_LARGE_CCW_ARC_TO_NV", + }, + { + 0x1700, "GL_PATH_MODELVIEW_NV", + }, + { + 0x1701, "GL_PATH_PROJECTION_NV", }, { 0x1702, "GL_TEXTURE", }, { + 0x18, "GL_LARGE_CW_ARC_TO_NV", + }, + { 0x1800, "GL_COLOR_EXT", }, { @@ -475,6 +568,9 @@ 0x1802, "GL_STENCIL_EXT", }, { + 0x19, "GL_RELATIVE_LARGE_CW_ARC_TO_NV", + }, + { 0x1901, "GL_STENCIL_INDEX_OES", }, { @@ -505,7 +601,19 @@ 0x190A, "GL_LUMINANCE_ALPHA", }, { - 0x1A, "GL_CONIC_CURVE_TO_CHROMIUM", + 0x1A, "GL_CONIC_CURVE_TO_NV", + }, + { + 0x1B, "GL_RELATIVE_CONIC_CURVE_TO_NV", + }, + { + 0x1B00, "GL_POINT_NV", + }, + { + 0x1B01, "GL_LINE_NV", + }, + { + 0x1B02, "GL_FILL_NV", }, { 0x1D00, "GL_FLAT_CHROMIUM", @@ -538,7 +646,10 @@ 0x2, "GL_CA_LAYER_EDGE_RIGHT_CHROMIUM", }, { - 0x20000000, "GL_MULTISAMPLE_BUFFER_BIT5_QCOM", + 0x20, "GL_GLYPH_VERTICAL_BEARING_X_BIT_NV", + }, + { + 0x20000000, "GL_FONT_NUM_GLYPH_INDICES_BIT_NV", }, { 0x2400, "GL_EYE_LINEAR_CHROMIUM", @@ -583,6 +694,12 @@ 0x2A00, "GL_POLYGON_OFFSET_UNITS", }, { + 0x2A01, "GL_POLYGON_OFFSET_POINT_NV", + }, + { + 0x2A02, "GL_POLYGON_OFFSET_LINE_NV", + }, + { 0x3000, "GL_CLIP_DISTANCE0_APPLE", }, { @@ -613,6 +730,9 @@ 0x4, "GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM", }, { + 0x40, "GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV", + }, + { 0x40000000, "GL_MULTISAMPLE_BUFFER_BIT6_QCOM", }, { @@ -652,6 +772,9 @@ 0x8, "GL_CA_LAYER_EDGE_TOP_CHROMIUM", }, { + 0x80, "GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV", + }, + { 0x80000000, "GL_MULTISAMPLE_BUFFER_BIT7_QCOM", }, { @@ -673,10 +796,10 @@ 0x8006, "GL_FUNC_ADD", }, { - 0x8007, "GL_MIN_EXT", + 0x8007, "GL_MIN", }, { - 0x8008, "GL_MAX_EXT", + 0x8008, "GL_MAX", }, { 0x8009, "GL_BLEND_EQUATION", @@ -718,6 +841,9 @@ 0x8052, "GL_RGB10_EXT", }, { + 0x8054, "GL_RGB16_EXT", + }, + { 0x8056, "GL_RGBA4", }, { @@ -730,6 +856,9 @@ 0x8059, "GL_RGB10_A2_EXT", }, { + 0x805B, "GL_RGBA16_EXT", + }, + { 0x8069, "GL_TEXTURE_BINDING_2D", }, { @@ -799,7 +928,7 @@ 0x80E9, "GL_MAX_ELEMENTS_INDICES", }, { - 0x812D, "GL_CLAMP_TO_BORDER_EXT", + 0x812D, "GL_CLAMP_TO_BORDER_OES", }, { 0x812F, "GL_CLAMP_TO_EDGE", @@ -871,7 +1000,13 @@ 0x821D, "GL_NUM_EXTENSIONS", }, { - 0x8221, "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED", + 0x821F, "GL_BUFFER_IMMUTABLE_STORAGE_EXT", + }, + { + 0x8220, "GL_BUFFER_STORAGE_FLAGS_EXT", + }, + { + 0x8221, "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES", }, { 0x8227, "GL_RG_EXT", @@ -883,9 +1018,15 @@ 0x8229, "GL_R8_EXT", }, { + 0x822A, "GL_R16_EXT", + }, + { 0x822B, "GL_RG8_EXT", }, { + 0x822C, "GL_RG16_EXT", + }, + { 0x822D, "GL_R16F_EXT", }, { @@ -1009,10 +1150,22 @@ 0x825A, "GL_PROGRAM_PIPELINE_BINDING_EXT", }, { - 0x825E, "GL_LAYER_PROVOKING_VERTEX_EXT", + 0x825B, "GL_MAX_VIEWPORTS_OES", }, { - 0x8260, "GL_UNDEFINED_VERTEX_EXT", + 0x825C, "GL_VIEWPORT_SUBPIXEL_BITS_OES", + }, + { + 0x825D, "GL_VIEWPORT_BOUNDS_RANGE_OES", + }, + { + 0x825E, "GL_LAYER_PROVOKING_VERTEX_OES", + }, + { + 0x825F, "GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES", + }, + { + 0x8260, "GL_UNDEFINED_VERTEX_OES", }, { 0x8261, "GL_NO_RESET_NOTIFICATION_KHR", @@ -1036,16 +1189,16 @@ 0x826D, "GL_DEBUG_GROUP_STACK_DEPTH_KHR", }, { - 0x82DB, "GL_TEXTURE_VIEW_MIN_LEVEL_EXT", + 0x82DB, "GL_TEXTURE_VIEW_MIN_LEVEL_OES", }, { - 0x82DC, "GL_TEXTURE_VIEW_NUM_LEVELS_EXT", + 0x82DC, "GL_TEXTURE_VIEW_NUM_LEVELS_OES", }, { - 0x82DD, "GL_TEXTURE_VIEW_MIN_LAYER_EXT", + 0x82DD, "GL_TEXTURE_VIEW_MIN_LAYER_OES", }, { - 0x82DE, "GL_TEXTURE_VIEW_NUM_LAYERS_EXT", + 0x82DE, "GL_TEXTURE_VIEW_NUM_LAYERS_OES", }, { 0x82DF, "GL_TEXTURE_IMMUTABLE_LEVELS", @@ -1063,12 +1216,21 @@ 0x82E3, "GL_QUERY_KHR", }, { + 0x82E4, "GL_PROGRAM_PIPELINE_KHR", + }, + { 0x82E6, "GL_SAMPLER_KHR", }, { 0x82E8, "GL_MAX_LABEL_LENGTH_KHR", }, { + 0x82F9, "GL_MAX_CULL_DISTANCES_EXT", + }, + { + 0x82FA, "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT", + }, + { 0x82FB, "GL_CONTEXT_RELEASE_BEHAVIOR_KHR", }, { @@ -1111,6 +1273,9 @@ 0x83FB, "GL_PERFQUERY_WAIT_INTEL", }, { + 0x83FE, "GL_CONSERVATIVE_RASTERIZATION_INTEL", + }, + { 0x846D, "GL_ALIASED_POINT_SIZE_RANGE", }, { @@ -1216,6 +1381,12 @@ 0x84E0, "GL_ACTIVE_TEXTURE", }, { + 0x84E3, "GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV", + }, + { + 0x84E4, "GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV", + }, + { 0x84E8, "GL_MAX_RENDERBUFFER_SIZE", }, { @@ -1477,16 +1648,16 @@ 0x886A, "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED", }, { - 0x886C, "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT", + 0x886C, "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES", }, { - 0x886D, "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT", + 0x886D, "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES", }, { 0x8872, "GL_MAX_TEXTURE_IMAGE_UNITS", }, { - 0x887F, "GL_GEOMETRY_SHADER_INVOCATIONS_EXT", + 0x887F, "GL_GEOMETRY_SHADER_INVOCATIONS_OES", }, { 0x8892, "GL_ARRAY_BUFFER", @@ -1597,13 +1768,13 @@ 0x8914, "GL_SAMPLES_PASSED_ARB", }, { - 0x8916, "GL_GEOMETRY_LINKED_VERTICES_OUT_EXT", + 0x8916, "GL_GEOMETRY_LINKED_VERTICES_OUT_OES", }, { - 0x8917, "GL_GEOMETRY_LINKED_INPUT_TYPE_EXT", + 0x8917, "GL_GEOMETRY_LINKED_INPUT_TYPE_OES", }, { - 0x8918, "GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT", + 0x8918, "GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES", }, { 0x8919, "GL_SAMPLER_BINDING", @@ -1627,7 +1798,7 @@ 0x8A2B, "GL_MAX_VERTEX_UNIFORM_BLOCKS", }, { - 0x8A2C, "GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT", + 0x8A2C, "GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES", }, { 0x8A2D, "GL_MAX_FRAGMENT_UNIFORM_BLOCKS", @@ -1645,7 +1816,7 @@ 0x8A31, "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", }, { - 0x8A32, "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT", + 0x8A32, "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES", }, { 0x8A33, "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", @@ -1972,6 +2143,12 @@ 0x8BDC, "GL_STATE_RESTORE", }, { + 0x8BE7, "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT", + }, + { + 0x8BFA, "GL_TEXTURE_PROTECTED_EXT", + }, + { 0x8C00, "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG", }, { @@ -1996,19 +2173,19 @@ 0x8C1D, "GL_TEXTURE_BINDING_2D_ARRAY", }, { - 0x8C29, "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT", + 0x8C29, "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES", }, { - 0x8C2A, "GL_TEXTURE_BUFFER_EXT", + 0x8C2A, "GL_TEXTURE_BUFFER_OES", }, { - 0x8C2B, "GL_MAX_TEXTURE_BUFFER_SIZE_EXT", + 0x8C2B, "GL_MAX_TEXTURE_BUFFER_SIZE_OES", }, { - 0x8C2C, "GL_TEXTURE_BINDING_BUFFER_EXT", + 0x8C2C, "GL_TEXTURE_BINDING_BUFFER_OES", }, { - 0x8C2D, "GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT", + 0x8C2D, "GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES", }, { 0x8C2F, "GL_ANY_SAMPLES_PASSED_EXT", @@ -2086,7 +2263,7 @@ 0x8C85, "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE", }, { - 0x8C87, "GL_PRIMITIVES_GENERATED_EXT", + 0x8C87, "GL_PRIMITIVES_GENERATED_OES", }, { 0x8C88, "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN", @@ -2233,6 +2410,54 @@ 0x8CEF, "GL_COLOR_ATTACHMENT15_EXT", }, { + 0x8CF0, "GL_COLOR_ATTACHMENT16", + }, + { + 0x8CF1, "GL_COLOR_ATTACHMENT17", + }, + { + 0x8CF2, "GL_COLOR_ATTACHMENT18", + }, + { + 0x8CF3, "GL_COLOR_ATTACHMENT19", + }, + { + 0x8CF4, "GL_COLOR_ATTACHMENT20", + }, + { + 0x8CF5, "GL_COLOR_ATTACHMENT21", + }, + { + 0x8CF6, "GL_COLOR_ATTACHMENT22", + }, + { + 0x8CF7, "GL_COLOR_ATTACHMENT23", + }, + { + 0x8CF8, "GL_COLOR_ATTACHMENT24", + }, + { + 0x8CF9, "GL_COLOR_ATTACHMENT25", + }, + { + 0x8CFA, "GL_COLOR_ATTACHMENT26", + }, + { + 0x8CFB, "GL_COLOR_ATTACHMENT27", + }, + { + 0x8CFC, "GL_COLOR_ATTACHMENT28", + }, + { + 0x8CFD, "GL_COLOR_ATTACHMENT29", + }, + { + 0x8CFE, "GL_COLOR_ATTACHMENT30", + }, + { + 0x8CFF, "GL_COLOR_ATTACHMENT31", + }, + { 0x8D00, "GL_DEPTH_ATTACHMENT", }, { @@ -2368,10 +2593,10 @@ 0x8D9F, "GL_INT_2_10_10_10_REV", }, { - 0x8DA7, "GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT", + 0x8DA7, "GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES", }, { - 0x8DA8, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT", + 0x8DA8, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES", }, { 0x8DAD, "GL_FLOAT_32_UNSIGNED_INT_24_8_REV", @@ -2383,7 +2608,7 @@ 0x8DC1, "GL_SAMPLER_2D_ARRAY", }, { - 0x8DC2, "GL_SAMPLER_BUFFER_EXT", + 0x8DC2, "GL_SAMPLER_BUFFER_OES", }, { 0x8DC4, "GL_SAMPLER_2D_ARRAY_SHADOW_NV", @@ -2413,7 +2638,7 @@ 0x8DCF, "GL_INT_SAMPLER_2D_ARRAY", }, { - 0x8DD0, "GL_INT_SAMPLER_BUFFER_EXT", + 0x8DD0, "GL_INT_SAMPLER_BUFFER_OES", }, { 0x8DD2, "GL_UNSIGNED_INT_SAMPLER_2D", @@ -2428,19 +2653,19 @@ 0x8DD7, "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY", }, { - 0x8DD8, "GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT", + 0x8DD8, "GL_UNSIGNED_INT_SAMPLER_BUFFER_OES", }, { - 0x8DD9, "GL_GEOMETRY_SHADER_EXT", + 0x8DD9, "GL_GEOMETRY_SHADER_OES", }, { - 0x8DDF, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT", + 0x8DDF, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES", }, { - 0x8DE0, "GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT", + 0x8DE0, "GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES", }, { - 0x8DE1, "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT", + 0x8DE1, "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES", }, { 0x8DF0, "GL_LOW_FLOAT", @@ -2485,10 +2710,28 @@ 0x8DFD, "GL_MAX_FRAGMENT_UNIFORM_VECTORS", }, { - 0x8E1E, "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT", + 0x8E13, "GL_QUERY_WAIT_NV", }, { - 0x8E1F, "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT", + 0x8E14, "GL_QUERY_NO_WAIT_NV", + }, + { + 0x8E15, "GL_QUERY_BY_REGION_WAIT_NV", + }, + { + 0x8E16, "GL_QUERY_BY_REGION_NO_WAIT_NV", + }, + { + 0x8E1B, "GL_POLYGON_OFFSET_CLAMP_EXT", + }, + { + 0x8E1E, "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES", + }, + { + 0x8E1F, "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES", + }, + { + 0x8E20, "GL_COLOR_SAMPLES_NV", }, { 0x8E22, "GL_TRANSFORM_FEEDBACK", @@ -2521,13 +2764,16 @@ 0x8E45, "GL_TEXTURE_SWIZZLE_A", }, { - 0x8E4D, "GL_FIRST_VERTEX_CONVENTION_EXT", + 0x8E4D, "GL_FIRST_VERTEX_CONVENTION_OES", }, { - 0x8E4E, "GL_LAST_VERTEX_CONVENTION_EXT", + 0x8E4E, "GL_LAST_VERTEX_CONVENTION_OES", }, { - 0x8E5A, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT", + 0x8E50, "GL_SAMPLE_LOCATION_NV", + }, + { + 0x8E5A, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES", }, { 0x8E5B, "GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES", @@ -2539,73 +2785,73 @@ 0x8E5D, "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES", }, { - 0x8E72, "GL_PATCH_VERTICES_EXT", + 0x8E72, "GL_PATCH_VERTICES_OES", }, { - 0x8E75, "GL_TESS_CONTROL_OUTPUT_VERTICES_EXT", + 0x8E75, "GL_TESS_CONTROL_OUTPUT_VERTICES_OES", }, { - 0x8E76, "GL_TESS_GEN_MODE_EXT", + 0x8E76, "GL_TESS_GEN_MODE_OES", }, { - 0x8E77, "GL_TESS_GEN_SPACING_EXT", + 0x8E77, "GL_TESS_GEN_SPACING_OES", }, { - 0x8E78, "GL_TESS_GEN_VERTEX_ORDER_EXT", + 0x8E78, "GL_TESS_GEN_VERTEX_ORDER_OES", }, { - 0x8E79, "GL_TESS_GEN_POINT_MODE_EXT", + 0x8E79, "GL_TESS_GEN_POINT_MODE_OES", }, { - 0x8E7A, "GL_ISOLINES_EXT", + 0x8E7A, "GL_ISOLINES_OES", }, { - 0x8E7B, "GL_FRACTIONAL_ODD_EXT", + 0x8E7B, "GL_FRACTIONAL_ODD_OES", }, { - 0x8E7C, "GL_FRACTIONAL_EVEN_EXT", + 0x8E7C, "GL_FRACTIONAL_EVEN_OES", }, { - 0x8E7D, "GL_MAX_PATCH_VERTICES_EXT", + 0x8E7D, "GL_MAX_PATCH_VERTICES_OES", }, { - 0x8E7E, "GL_MAX_TESS_GEN_LEVEL_EXT", + 0x8E7E, "GL_MAX_TESS_GEN_LEVEL_OES", }, { - 0x8E7F, "GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT", + 0x8E7F, "GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES", }, { - 0x8E80, "GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT", + 0x8E80, "GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES", }, { - 0x8E81, "GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT", + 0x8E81, "GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES", }, { - 0x8E82, "GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT", + 0x8E82, "GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES", }, { - 0x8E83, "GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT", + 0x8E83, "GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES", }, { - 0x8E84, "GL_MAX_TESS_PATCH_COMPONENTS_EXT", + 0x8E84, "GL_MAX_TESS_PATCH_COMPONENTS_OES", }, { - 0x8E85, "GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT", + 0x8E85, "GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES", }, { - 0x8E86, "GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT", + 0x8E86, "GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES", }, { - 0x8E87, "GL_TESS_EVALUATION_SHADER_EXT", + 0x8E87, "GL_TESS_EVALUATION_SHADER_OES", }, { - 0x8E88, "GL_TESS_CONTROL_SHADER_EXT", + 0x8E88, "GL_TESS_CONTROL_SHADER_OES", }, { - 0x8E89, "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT", + 0x8E89, "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES", }, { - 0x8E8A, "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT", + 0x8E8A, "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES", }, { 0x8ED0, "GL_COVERAGE_COMPONENT_NV", @@ -2632,6 +2878,24 @@ 0x8ED7, "GL_COVERAGE_AUTOMATIC_NV", }, { + 0x8F10, "GL_INCLUSIVE_EXT", + }, + { + 0x8F11, "GL_EXCLUSIVE_EXT", + }, + { + 0x8F12, "GL_WINDOW_RECTANGLE_EXT", + }, + { + 0x8F13, "GL_WINDOW_RECTANGLE_MODE_EXT", + }, + { + 0x8F14, "GL_MAX_WINDOW_RECTANGLES_EXT", + }, + { + 0x8F15, "GL_NUM_WINDOW_RECTANGLES_EXT", + }, + { 0x8F36, "GL_COPY_READ_BUFFER_NV", }, { @@ -2659,6 +2923,9 @@ 0x8F67, "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT", }, { + 0x8F69, "GL_TEXTURE_ASTC_DECODE_PRECISION_EXT", + }, + { 0x8F94, "GL_R8_SNORM", }, { @@ -2671,6 +2938,18 @@ 0x8F97, "GL_RGBA8_SNORM", }, { + 0x8F98, "GL_R16_SNORM_EXT", + }, + { + 0x8F99, "GL_RG16_SNORM_EXT", + }, + { + 0x8F9A, "GL_RGB16_SNORM_EXT", + }, + { + 0x8F9B, "GL_RGBA16_SNORM_EXT", + }, + { 0x8F9C, "GL_SIGNED_NORMALIZED", }, { @@ -2692,136 +2971,355 @@ 0x8FBB, "GL_GPU_DISJOINT_EXT", }, { + 0x8FBD, "GL_SR8_EXT", + }, + { + 0x8FBE, "GL_SRG8_EXT", + }, + { 0x8FC4, "GL_SHADER_BINARY_VIV", }, { - 0x9009, "GL_TEXTURE_CUBE_MAP_ARRAY_EXT", + 0x8FE0, "GL_INT8_NV", }, { - 0x900A, "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT", + 0x8FE1, "GL_INT8_VEC2_NV", }, { - 0x900C, "GL_SAMPLER_CUBE_MAP_ARRAY_EXT", + 0x8FE2, "GL_INT8_VEC3_NV", }, { - 0x900D, "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT", + 0x8FE3, "GL_INT8_VEC4_NV", }, { - 0x900E, "GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT", + 0x8FE4, "GL_INT16_NV", }, { - 0x900F, "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT", + 0x8FE5, "GL_INT16_VEC2_NV", }, { - 0x9051, "GL_IMAGE_BUFFER_EXT", + 0x8FE6, "GL_INT16_VEC3_NV", }, { - 0x9054, "GL_IMAGE_CUBE_MAP_ARRAY_EXT", + 0x8FE7, "GL_INT16_VEC4_NV", }, { - 0x905C, "GL_INT_IMAGE_BUFFER_EXT", + 0x8FE9, "GL_INT64_VEC2_NV", }, { - 0x905F, "GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT", + 0x8FEA, "GL_INT64_VEC3_NV", }, { - 0x9067, "GL_UNSIGNED_INT_IMAGE_BUFFER_EXT", + 0x8FEB, "GL_INT64_VEC4_NV", }, { - 0x906A, "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT", + 0x8FEC, "GL_UNSIGNED_INT8_NV", + }, + { + 0x8FED, "GL_UNSIGNED_INT8_VEC2_NV", + }, + { + 0x8FEE, "GL_UNSIGNED_INT8_VEC3_NV", + }, + { + 0x8FEF, "GL_UNSIGNED_INT8_VEC4_NV", + }, + { + 0x8FF0, "GL_UNSIGNED_INT16_NV", + }, + { + 0x8FF1, "GL_UNSIGNED_INT16_VEC2_NV", + }, + { + 0x8FF2, "GL_UNSIGNED_INT16_VEC3_NV", + }, + { + 0x8FF3, "GL_UNSIGNED_INT16_VEC4_NV", + }, + { + 0x8FF5, "GL_UNSIGNED_INT64_VEC2_NV", + }, + { + 0x8FF6, "GL_UNSIGNED_INT64_VEC3_NV", + }, + { + 0x8FF7, "GL_UNSIGNED_INT64_VEC4_NV", + }, + { + 0x8FF8, "GL_FLOAT16_NV", + }, + { + 0x8FF9, "GL_FLOAT16_VEC2_NV", + }, + { + 0x8FFA, "GL_FLOAT16_VEC3_NV", + }, + { + 0x8FFB, "GL_FLOAT16_VEC4_NV", + }, + { + 0x9009, "GL_TEXTURE_CUBE_MAP_ARRAY_OES", + }, + { + 0x900A, "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES", + }, + { + 0x900C, "GL_SAMPLER_CUBE_MAP_ARRAY_OES", + }, + { + 0x900D, "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES", + }, + { + 0x900E, "GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES", + }, + { + 0x900F, "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES", + }, + { + 0x9051, "GL_IMAGE_BUFFER_OES", + }, + { + 0x9054, "GL_IMAGE_CUBE_MAP_ARRAY_OES", + }, + { + 0x905C, "GL_INT_IMAGE_BUFFER_OES", + }, + { + 0x905F, "GL_INT_IMAGE_CUBE_MAP_ARRAY_OES", + }, + { + 0x9067, "GL_UNSIGNED_INT_IMAGE_BUFFER_OES", + }, + { + 0x906A, "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES", }, { 0x906F, "GL_RGB10_A2UI", }, { - 0x9075, "GL_PATH_STROKE_WIDTH_CHROMIUM", + 0x9070, "GL_PATH_FORMAT_SVG_NV", }, { - 0x9076, "GL_PATH_END_CAPS_CHROMIUM", + 0x9071, "GL_PATH_FORMAT_PS_NV", }, { - 0x9079, "GL_PATH_JOIN_STYLE_CHROMIUM", + 0x9072, "GL_STANDARD_FONT_NAME_NV", + }, + { + 0x9073, "GL_SYSTEM_FONT_NAME_NV", + }, + { + 0x9074, "GL_FILE_NAME_NV", + }, + { + 0x9075, "GL_PATH_STROKE_WIDTH_NV", + }, + { + 0x9076, "GL_PATH_END_CAPS_NV", + }, + { + 0x9077, "GL_PATH_INITIAL_END_CAP_NV", + }, + { + 0x9078, "GL_PATH_TERMINAL_END_CAP_NV", + }, + { + 0x9079, "GL_PATH_JOIN_STYLE_NV", + }, + { + 0x907A, "GL_PATH_MITER_LIMIT_NV", + }, + { + 0x907B, "GL_PATH_DASH_CAPS_NV", + }, + { + 0x907C, "GL_PATH_INITIAL_DASH_CAP_NV", + }, + { + 0x907D, "GL_PATH_TERMINAL_DASH_CAP_NV", + }, + { + 0x907E, "GL_PATH_DASH_OFFSET_NV", + }, + { + 0x907F, "GL_PATH_CLIENT_LENGTH_NV", }, { 0x907a, "GL_PATH_MITER_LIMIT_CHROMIUM", }, { + 0x9080, "GL_PATH_FILL_MODE_NV", + }, + { + 0x9081, "GL_PATH_FILL_MASK_NV", + }, + { + 0x9082, "GL_PATH_FILL_COVER_MODE_NV", + }, + { + 0x9083, "GL_PATH_STROKE_COVER_MODE_NV", + }, + { + 0x9084, "GL_PATH_STROKE_MASK_NV", + }, + { 0x9086, "GL_PATH_STROKE_BOUND_CHROMIUM", }, { - 0x9088, "GL_COUNT_UP_CHROMIUM", + 0x9088, "GL_COUNT_UP_NV", }, { - 0x9089, "GL_COUNT_DOWN_CHROMIUM", + 0x9089, "GL_COUNT_DOWN_NV", }, { - 0x908B, "GL_CONVEX_HULL_CHROMIUM", + 0x908A, "GL_PATH_OBJECT_BOUNDING_BOX_NV", }, { - 0x908D, "GL_BOUNDING_BOX_CHROMIUM", + 0x908B, "GL_CONVEX_HULL_NV", }, { - 0x908E, "GL_TRANSLATE_X_CHROMIUM", + 0x908D, "GL_BOUNDING_BOX_NV", }, { - 0x908F, "GL_TRANSLATE_Y_CHROMIUM", + 0x908E, "GL_TRANSLATE_X_NV", }, { - 0x9090, "GL_TRANSLATE_2D_CHROMIUM", + 0x908F, "GL_TRANSLATE_Y_NV", }, { - 0x9091, "GL_TRANSLATE_3D_CHROMIUM", + 0x9090, "GL_TRANSLATE_2D_NV", }, { - 0x9092, "GL_AFFINE_2D_CHROMIUM", + 0x9091, "GL_TRANSLATE_3D_NV", }, { - 0x9094, "GL_AFFINE_3D_CHROMIUM", + 0x9092, "GL_AFFINE_2D_NV", }, { - 0x9096, "GL_TRANSPOSE_AFFINE_2D_CHROMIUM", + 0x9094, "GL_AFFINE_3D_NV", }, { - 0x9098, "GL_TRANSPOSE_AFFINE_3D_CHROMIUM", + 0x9096, "GL_TRANSPOSE_AFFINE_2D_NV", }, { - 0x909C, "GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM", + 0x9098, "GL_TRANSPOSE_AFFINE_3D_NV", }, { - 0x90A4, "GL_ROUND_CHROMIUM", + 0x909A, "GL_UTF8_NV", }, { - 0x90A6, "GL_BEVEL_CHROMIUM", + 0x909B, "GL_UTF16_NV", }, { - 0x90A7, "GL_MITER_REVERT_CHROMIUM", + 0x909C, "GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV", }, { - 0x90B7, "GL_PATH_STENCIL_FUNC_CHROMIUM", + 0x909D, "GL_PATH_COMMAND_COUNT_NV", }, { - 0x90B8, "GL_PATH_STENCIL_REF_CHROMIUM", + 0x909E, "GL_PATH_COORD_COUNT_NV", }, { - 0x90B9, "GL_PATH_STENCIL_VALUE_MASK_CHROMIUM", + 0x909F, "GL_PATH_DASH_ARRAY_COUNT_NV", }, { - 0x90CB, "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT", + 0x90A0, "GL_PATH_COMPUTED_LENGTH_NV", }, { - 0x90CC, "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT", + 0x90A1, "GL_PATH_FILL_BOUNDING_BOX_NV", }, { - 0x90CD, "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT", + 0x90A2, "GL_PATH_STROKE_BOUNDING_BOX_NV", }, { - 0x90D7, "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT", + 0x90A3, "GL_SQUARE_NV", }, { - 0x90D8, "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT", + 0x90A4, "GL_ROUND_NV", }, { - 0x90D9, "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT", + 0x90A5, "GL_TRIANGULAR_NV", + }, + { + 0x90A6, "GL_BEVEL_NV", + }, + { + 0x90A7, "GL_MITER_REVERT_NV", + }, + { + 0x90A8, "GL_MITER_TRUNCATE_NV", + }, + { + 0x90A9, "GL_SKIP_MISSING_GLYPH_NV", + }, + { + 0x90AA, "GL_USE_MISSING_GLYPH_NV", + }, + { + 0x90AB, "GL_PATH_ERROR_POSITION_NV", + }, + { + 0x90AD, "GL_ACCUM_ADJACENT_PAIRS_NV", + }, + { + 0x90AE, "GL_ADJACENT_PAIRS_NV", + }, + { + 0x90AF, "GL_FIRST_TO_REST_NV", + }, + { + 0x90B0, "GL_PATH_GEN_MODE_NV", + }, + { + 0x90B1, "GL_PATH_GEN_COEFF_NV", + }, + { + 0x90B3, "GL_PATH_GEN_COMPONENTS_NV", + }, + { + 0x90B4, "GL_PATH_DASH_OFFSET_RESET_NV", + }, + { + 0x90B5, "GL_MOVE_TO_RESETS_NV", + }, + { + 0x90B6, "GL_MOVE_TO_CONTINUES_NV", + }, + { + 0x90B7, "GL_PATH_STENCIL_FUNC_NV", + }, + { + 0x90B8, "GL_PATH_STENCIL_REF_NV", + }, + { + 0x90B9, "GL_PATH_STENCIL_VALUE_MASK_NV", + }, + { + 0x90BD, "GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV", + }, + { + 0x90BE, "GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV", + }, + { + 0x90BF, "GL_PATH_COVER_DEPTH_FUNC_NV", + }, + { + 0x90CB, "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES", + }, + { + 0x90CC, "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES", + }, + { + 0x90CD, "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES", + }, + { + 0x90D7, "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES", + }, + { + 0x90D8, "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES", + }, + { + 0x90D9, "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES", }, { 0x90F0, "GL_COLOR_ATTACHMENT_EXT", @@ -2842,6 +3340,9 @@ 0x90a4, "GL_ROUND_CHROMIUM", }, { + 0x9100, "GL_TEXTURE_2D_MULTISAMPLE", + }, + { 0x9102, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES", }, { @@ -2908,10 +3409,10 @@ 0x9122, "GL_MAX_VERTEX_OUTPUT_COMPONENTS", }, { - 0x9123, "GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT", + 0x9123, "GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES", }, { - 0x9124, "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT", + 0x9124, "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES", }, { 0x9125, "GL_MAX_FRAGMENT_INPUT_COMPONENTS", @@ -2941,6 +3442,27 @@ 0x9138, "GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG", }, { + 0x9139, "GL_CUBIC_IMG", + }, + { + 0x913A, "GL_CUBIC_MIPMAP_NEAREST_IMG", + }, + { + 0x913B, "GL_CUBIC_MIPMAP_LINEAR_IMG", + }, + { + 0x913C, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG", + }, + { + 0x913D, "GL_NUM_DOWNSAMPLE_SCALES_IMG", + }, + { + 0x913E, "GL_DOWNSAMPLE_SCALES_IMG", + }, + { + 0x913F, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG", + }, + { 0x9143, "GL_MAX_DEBUG_MESSAGE_LENGTH_KHR", }, { @@ -2968,13 +3490,46 @@ 0x9154, "GL_VERTEX_ARRAY_OBJECT_EXT", }, { - 0x919D, "GL_TEXTURE_BUFFER_OFFSET_EXT", + 0x9195, "GL_VIRTUAL_PAGE_SIZE_X_EXT", }, { - 0x919E, "GL_TEXTURE_BUFFER_SIZE_EXT", + 0x9196, "GL_VIRTUAL_PAGE_SIZE_Y_EXT", }, { - 0x919F, "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT", + 0x9197, "GL_VIRTUAL_PAGE_SIZE_Z_EXT", + }, + { + 0x9198, "GL_MAX_SPARSE_TEXTURE_SIZE_EXT", + }, + { + 0x9199, "GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT", + }, + { + 0x919A, "GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT", + }, + { + 0x919D, "GL_TEXTURE_BUFFER_OFFSET_OES", + }, + { + 0x919E, "GL_TEXTURE_BUFFER_SIZE_OES", + }, + { + 0x919F, "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES", + }, + { + 0x91A6, "GL_TEXTURE_SPARSE_EXT", + }, + { + 0x91A7, "GL_VIRTUAL_PAGE_SIZE_INDEX_EXT", + }, + { + 0x91A8, "GL_NUM_VIRTUAL_PAGE_SIZES_EXT", + }, + { + 0x91A9, "GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT", + }, + { + 0x91AA, "GL_NUM_SPARSE_LEVELS_EXT", }, { 0x9243, "GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM", @@ -3184,49 +3739,196 @@ 0x92B4, "GL_INVERT_OVG_NV", }, { - 0x92BE, "GL_PRIMITIVE_BOUNDING_BOX_EXT", + 0x92BE, "GL_PRIMITIVE_BOUNDING_BOX_OES", }, { - 0x92CD, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT", + 0x92CD, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES", }, { - 0x92CE, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT", + 0x92CE, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES", }, { - 0x92CF, "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT", + 0x92CF, "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES", }, { - 0x92D3, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT", + 0x92D3, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES", }, { - 0x92D4, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT", + 0x92D4, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES", }, { - 0x92D5, "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT", + 0x92D5, "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES", + }, + { + 0x92DD, "GL_FRAGMENT_COVERAGE_TO_COLOR_NV", + }, + { + 0x92DE, "GL_FRAGMENT_COVERAGE_COLOR_NV", }, { 0x92E0, "GL_DEBUG_OUTPUT_KHR", }, { - 0x92E7, "GL_IS_PER_PATCH_EXT", + 0x92E7, "GL_IS_PER_PATCH_OES", }, { - 0x9307, "GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT", + 0x9307, "GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES", }, { - 0x9308, "GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT", + 0x9308, "GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES", }, { - 0x9309, "GL_REFERENCED_BY_GEOMETRY_SHADER_EXT", + 0x9309, "GL_REFERENCED_BY_GEOMETRY_SHADER_OES", }, { - 0x9312, "GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT", + 0x930F, "GL_LOCATION_INDEX_EXT", }, { - 0x9317, "GL_MAX_FRAMEBUFFER_LAYERS_EXT", + 0x9312, "GL_FRAMEBUFFER_DEFAULT_LAYERS_OES", }, { - 0x9332, "GL_COVERAGE_MODULATION_CHROMIUM", + 0x9317, "GL_MAX_FRAMEBUFFER_LAYERS_OES", + }, + { + 0x9327, "GL_RASTER_MULTISAMPLE_EXT", + }, + { + 0x9328, "GL_RASTER_SAMPLES_EXT", + }, + { + 0x9329, "GL_MAX_RASTER_SAMPLES_EXT", + }, + { + 0x932A, "GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT", + }, + { + 0x932B, "GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT", + }, + { + 0x932C, "GL_EFFECTIVE_RASTER_SAMPLES_EXT", + }, + { + 0x932D, "GL_DEPTH_SAMPLES_NV", + }, + { + 0x932E, "GL_STENCIL_SAMPLES_NV", + }, + { + 0x932F, "GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV", + }, + { + 0x9330, "GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV", + }, + { + 0x9331, "GL_COVERAGE_MODULATION_TABLE_NV", + }, + { + 0x9332, "GL_COVERAGE_MODULATION_NV", + }, + { + 0x9333, "GL_COVERAGE_MODULATION_TABLE_SIZE_NV", + }, + { + 0x933C, "GL_FILL_RECTANGLE_NV", + }, + { + 0x933D, "GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV", + }, + { + 0x933E, "GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV", + }, + { + 0x933F, "GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV", + }, + { + 0x9340, "GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV", + }, + { + 0x9341, "GL_PROGRAMMABLE_SAMPLE_LOCATION_NV", + }, + { + 0x9342, "GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV", + }, + { + 0x9343, "GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV", + }, + { + 0x9346, "GL_CONSERVATIVE_RASTERIZATION_NV", + }, + { + 0x9347, "GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV", + }, + { + 0x9348, "GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV", + }, + { + 0x9349, "GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV", + }, + { + 0x9350, "GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV", + }, + { + 0x9351, "GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV", + }, + { + 0x9352, "GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV", + }, + { + 0x9353, "GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV", + }, + { + 0x9354, "GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV", + }, + { + 0x9355, "GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV", + }, + { + 0x9356, "GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV", + }, + { + 0x9357, "GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV", + }, + { + 0x9358, "GL_VIEWPORT_SWIZZLE_X_NV", + }, + { + 0x9359, "GL_VIEWPORT_SWIZZLE_Y_NV", + }, + { + 0x935A, "GL_VIEWPORT_SWIZZLE_Z_NV", + }, + { + 0x935B, "GL_VIEWPORT_SWIZZLE_W_NV", + }, + { + 0x9368, "GL_FONT_GLYPHS_AVAILABLE_NV", + }, + { + 0x9369, "GL_FONT_TARGET_UNAVAILABLE_NV", + }, + { + 0x936A, "GL_FONT_UNAVAILABLE_NV", + }, + { + 0x936B, "GL_FONT_UNINTELLIGIBLE_NV", + }, + { + 0x936C, "GL_STANDARD_FONT_FORMAT_NV", + }, + { + 0x936D, "GL_FRAGMENT_INPUT_NV", + }, + { + 0x9371, "GL_MULTISAMPLES_NV", + }, + { + 0x9372, "GL_SUPERSAMPLE_SCALE_X_NV", + }, + { + 0x9373, "GL_SUPERSAMPLE_SCALE_Y_NV", + }, + { + 0x9374, "GL_CONFORMANT_NV", }, { 0x9380, "GL_NUM_SAMPLE_COUNTS", @@ -3445,10 +4147,99 @@ 0x9500, "GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL", }, { + 0x954D, "GL_CONSERVATIVE_RASTER_MODE_NV", + }, + { + 0x954E, "GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV", + }, + { + 0x954F, "GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV", + }, + { + 0x9630, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR", + }, + { + 0x9631, "GL_MAX_VIEWS_OVR", + }, + { + 0x9632, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR", + }, + { + 0x9633, "GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR", + }, + { + 0x9650, "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT", + }, + { + 0x9651, "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT", + }, + { + 0x9652, + "GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_" + "EXT", + }, + { + 0xC0, "GL_SHARED_EDGE_NV", + }, + { + 0xE8, "GL_ROUNDED_RECT_NV", + }, + { + 0xE9, "GL_RELATIVE_ROUNDED_RECT_NV", + }, + { + 0xEA, "GL_ROUNDED_RECT2_NV", + }, + { + 0xEB, "GL_RELATIVE_ROUNDED_RECT2_NV", + }, + { + 0xEC, "GL_ROUNDED_RECT4_NV", + }, + { + 0xED, "GL_RELATIVE_ROUNDED_RECT4_NV", + }, + { + 0xEE, "GL_ROUNDED_RECT8_NV", + }, + { + 0xEF, "GL_RELATIVE_ROUNDED_RECT8_NV", + }, + { + 0xF0, "GL_RESTART_PATH_NV", + }, + { + 0xF2, "GL_DUP_FIRST_CUBIC_CURVE_TO_NV", + }, + { + 0xF4, "GL_DUP_LAST_CUBIC_CURVE_TO_NV", + }, + { + 0xF6, "GL_RECT_NV", + }, + { + 0xF7, "GL_RELATIVE_RECT_NV", + }, + { + 0xF8, "GL_CIRCULAR_CCW_ARC_TO_NV", + }, + { + 0xFA, "GL_CIRCULAR_CW_ARC_TO_NV", + }, + { + 0xFC, "GL_CIRCULAR_TANGENT_ARC_TO_NV", + }, + { + 0xFE, "GL_ARC_TO_NV", + }, + { + 0xFF, "GL_RELATIVE_ARC_TO_NV", + }, + { 0xFFFFFFFF, "GL_ALL_SHADER_BITS_EXT", }, { - 1, "GL_ES_VERSION_2_0", + 1, "GL_GLES_PROTOTYPES", }, { 16, "GL_MAILBOX_SIZE_CHROMIUM",
diff --git a/ui/message_center/message_center_impl_unittest.cc b/ui/message_center/message_center_impl_unittest.cc index 84310e1..3ed12ed 100644 --- a/ui/message_center/message_center_impl_unittest.cc +++ b/ui/message_center/message_center_impl_unittest.cc
@@ -351,7 +351,7 @@ // Fast forward the |task_runner| by one second less than the auto-close timer // frequency for Web Notifications. (As set by the |notifier_id|.) task_runner->FastForwardBy( - base::TimeDelta::FromSeconds(kAutocloseWebPageDelaySeconds - 1)); + base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds - 1)); ASSERT_EQ(popup_timers_controller->timer_finished(), 0); // Trigger a replacement of the notification in the timer controller. @@ -360,7 +360,7 @@ // Fast forward the |task_runner| by one second less than the auto-close timer // frequency for Web Notifications again. It should have been reset. task_runner->FastForwardBy( - base::TimeDelta::FromSeconds(kAutocloseWebPageDelaySeconds - 1)); + base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds - 1)); ASSERT_EQ(popup_timers_controller->timer_finished(), 0); // Now fast forward the |task_runner| by two seconds (to avoid flakiness),
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h index 3eee4ae..be5acf24 100644 --- a/ui/message_center/message_center_style.h +++ b/ui/message_center/message_center_style.h
@@ -112,13 +112,11 @@ // Not used when --enabled-new-style-notification is set. const size_t kNotificationMaximumItems = 5; -// Timing. +// Timing. Web Notifications always use high-priority timings. Given the absence +// of a notification center on non-Chrome OS platforms, this improves users' +// ability to interact with the toasts. const int kAutocloseDefaultDelaySeconds = 8; const int kAutocloseHighPriorityDelaySeconds = 25; -// Web notifications use a larger timeout for now, which improves re-engagement. -// TODO(johnme): Use Finch to experiment with different values, then consider -// replacing kAutocloseDefaultDelaySeconds with this (https://crbug.com/530697) -const int kAutocloseWebPageDelaySeconds = 20; // Buttons. const int kButtonHeight = 38; // In DIPs.
diff --git a/ui/message_center/popup_timers_controller.cc b/ui/message_center/popup_timers_controller.cc index a967681..9be0a9e 100644 --- a/ui/message_center/popup_timers_controller.cc +++ b/ui/message_center/popup_timers_controller.cc
@@ -14,10 +14,10 @@ namespace { base::TimeDelta GetTimeoutForNotification(Notification* notification) { - if (notification->priority() > DEFAULT_PRIORITY) + if (notification->notifier_id().type == NotifierId::WEB_PAGE || + notification->priority() > DEFAULT_PRIORITY) { return base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds); - if (notification->notifier_id().type == NotifierId::WEB_PAGE) - return base::TimeDelta::FromSeconds(kAutocloseWebPageDelaySeconds); + } return base::TimeDelta::FromSeconds(kAutocloseDefaultDelaySeconds); }
diff --git a/ui/views/examples/examples_main.cc b/ui/views/examples/examples_main.cc index 67138c38..fd3c10d9 100644 --- a/ui/views/examples/examples_main.cc +++ b/ui/views/examples/examples_main.cc
@@ -67,10 +67,10 @@ gl::init::InitializeGLOneOff(); // The ContextFactory must exist before any Compositors are created. - viz::HostFrameSinkManager frame_sink_manager_; - cc::SurfaceManager surface_manager_; + viz::HostFrameSinkManager host_frame_sink_manager_; + cc::FrameSinkManager frame_sink_manager_; auto context_factory = base::MakeUnique<ui::InProcessContextFactory>( - &frame_sink_manager_, &surface_manager_); + &host_frame_sink_manager_, &frame_sink_manager_); context_factory->set_use_test_surface(false); base::MessageLoopForUI message_loop;
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html index b806cb8..8651c39 100644 --- a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html +++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
@@ -1,11 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/icons.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <dom-module id="cr-expand-button"> <template> - <style include="cr-shared-style"> + <style include="cr-icons cr-shared-style"> :host { display: inline-block; } @@ -14,16 +14,15 @@ pointer-events: none; } - paper-icon-button { + button[is=paper-icon-button-light] { @apply(--cr-paper-icon-button-margin); } </style> <content></content> - <paper-icon-button toggles active="{{expanded}}" disabled="[[disabled]]" - icon="[[iconName_(expanded)]]" alt="[[alt]]" - aria-active-attribute="aria-expanded" - on-tap="stopTap_"> - </paper-icon-button> + <button is="paper-icon-button-light" class$="[[iconName_(expanded)]]" + toggles active="{{expanded}}" disabled="[[disabled]]" alt="[[alt]]" + aria-active-attribute="aria-expanded" on-tap="toggleExpand_"> + </button> </template> <script src="cr_expand_button.js"></script> </dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js index 27d57d37..3756574 100644 --- a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js +++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js
@@ -4,12 +4,8 @@ /** * @fileoverview - * 'cr-expand-button' is a chrome-specific wrapper around paper-icon-button that - * toggles between an opened (expanded) and closed state. - * - * Example: - * - * <cr-expand-button expanded="{{sectionIsExpanded}}"></cr-expand-button> + * 'cr-expand-button' is a chrome-specific wrapper around a button that toggles + * between an opened (expanded) and closed state. */ Polymer({ is: 'cr-expand-button', @@ -22,7 +18,7 @@ expanded: {type: Boolean, value: false, notify: true}, /** - * If true, the button will be disabled and greyed out. + * If true, the button will be disabled and grayed out. */ disabled: {type: Boolean, value: false, reflectToAttribute: true}, @@ -30,15 +26,17 @@ alt: String, }, + /** @private */ iconName_: function(expanded) { - return expanded ? 'cr:expand-less' : 'cr:expand-more'; + return expanded ? 'icon-expand-less' : 'icon-expand-more'; }, /** - * @param {Event} event + * @param {!Event} event * @private */ - stopTap_: function(event) { + toggleExpand_: function(event) { + this.expanded = !this.expanded; event.stopPropagation(); }, });
diff --git a/ui/webui/resources/cr_elements/cr_icons_css.html b/ui/webui/resources/cr_elements/cr_icons_css.html index c9e35876..c8d7acb3 100644 --- a/ui/webui/resources/cr_elements/cr_icons_css.html +++ b/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -4,11 +4,6 @@ <dom-module id="cr-icons"> <template> <style> - button[is='paper-icon-button-light'].subpage-arrow, - paper-icon-button.subpage-arrow { - background-image: url(../images/arrow_right.svg); - } - button[is='paper-icon-button-light'].icon-cancel { background-image: url(../images/icon_cancel.svg); } @@ -25,6 +20,14 @@ background-image: url(../images/icon_delete.svg); } + button[is='paper-icon-button-light'].icon-expand-less { + background-image: url(../images/icon_expand_less.svg); + } + + button[is='paper-icon-button-light'].icon-expand-more { + background-image: url(../images/icon_expand_more.svg); + } + button[is='paper-icon-button-light'].icon-external { background-image: url(../images/open_in_new.svg); } @@ -44,6 +47,10 @@ button[is='paper-icon-button-light'].icon-arrow-dropdown { background-image: url(../images/icon_arrow_dropdown.svg); } + + button[is='paper-icon-button-light'].subpage-arrow { + background-image: url(../images/arrow_right.svg); + } </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 9b854cf5..4ce2020 100644 --- a/ui/webui/resources/cr_elements/shared_vars_css.html +++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -13,7 +13,7 @@ --cr-focused-item-color: var(--google-grey-300); - /* The inner icon is 20px in size. paper-icon-button has 8px padding. */ + /* The inner icon is 20px in size. The button has 8px * 2 padding. */ --cr-icon-ripple-size: 36px; --cr-icon-ripple-padding: 8px;
diff --git a/ui/webui/resources/cr_elements_images.grdp b/ui/webui/resources/cr_elements_images.grdp index 9cf3cab..c962220a 100644 --- a/ui/webui/resources/cr_elements_images.grdp +++ b/ui/webui/resources/cr_elements_images.grdp
@@ -1,5 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> + <!-- TODO(dschuyler): Many of these may be included for the unit tests which + don't appear to flatten the html. We may be able to avoid including + these if the browser_tests would not try to load them. --> <include name="IDR_WEBUI_IMAGES_ARROW_DOWN" file="images/arrow_down.svg" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_ARROW_RIGHT" @@ -14,6 +17,10 @@ file="images/icon_clear.svg" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_ICON_DELETE" file="images/icon_delete.svg" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_ICON_EXPAND_LESS" + file="images/icon_expand_less.svg" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_ICON_EXPAND_MORE" + file="images/icon_expand_more.svg" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_ICON_EXTERNAL" file="images/open_in_new.svg" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_ICON_MORE_VERT"
diff --git a/ui/webui/resources/images/icon_expand_less.svg b/ui/webui/resources/images/icon_expand_less.svg new file mode 100644 index 0000000..e8c6b5c --- /dev/null +++ b/ui/webui/resources/images/icon_expand_less.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="#757575" width="24" height="24" + viewbox="0 0 24 24"> + <path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path> +</svg>
diff --git a/ui/webui/resources/images/icon_expand_more.svg b/ui/webui/resources/images/icon_expand_more.svg new file mode 100644 index 0000000..05d9cbc --- /dev/null +++ b/ui/webui/resources/images/icon_expand_more.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="#757575" width="24" height="24" + viewBox="0 0 24 24"> + <path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path> +</svg>